这题刚开始以为模拟一下,最不济用一下二分,对于每一块地方,找到最先开始挖掘的下表,和最后结束的下标。注意这里面有重复元素,所以二分出来以后还需要判断.
class Solution {
public:
int digArtifacts(int n, vector<vector<int>>& artifacts, vector<vector<int>>& dig) {
// 默认按第一个元素大小排,然后相同的话按照第二个元素排
sort(dig.begin(), dig.end());
int res = 0;
for(int i = 0 ; i < artifacts.size(); i ++)
{
int x1 = artifacts[i][0];
int y1 = artifacts[i][1];
int x2 = artifacts[i][2];
int y2 = artifacts[i][3];
int fa = (x2 - x1 + 1) * (y2 - y1 + 1);
int son = 0;
// 找到第一个小于等于x1的下标
int ll , rr;
int l = 0, r = dig.size() - 1;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(dig[mid][0] <= x1) l = mid;
else r = mid - 1;
}
ll = l;
l = 0, r = dig.size() - 1;
while(l < r)//找第一个大于等于x2 的下标
{
int mid = l + r >> 1;
if(dig[mid][0] >= x2)r = mid;
else l = mid + 1;
}
rr = l;
while(ll > 0 && dig[ll][0] == dig[ll-1][0])ll --;
while(rr < dig.size()-1 && dig[rr][0] == dig[rr + 1][0])rr ++;
for(int j = ll; j <= rr;j ++)
{
int xx = dig[j][0];
int yy = dig[j][1];
if(xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2)
{
son ++;
}
}
if(fa == son)res ++;
}
return res;
}
};
但是最后一个样例过不了。因为最差是1e10,过不了
其实这题应该重点在于地图面积为1000 x 1000
对于所有的工件,开一个remap数组记录这些工件在哪里出现过,并且标上数字。另外还要记录一下每块组件的大小cnt
然后遍历dig数组,对于每一个挖掘,如果remap上有值,就记录挖到了,就把对应数组加1,如果该数组和cnt一样大,则答案加1
const int N = 1e3 + 10;
const int M = 1e5 + 10;
int remap[N][N];
int cnt[M],dis[M];
class Solution {
public:
int digArtifacts(int n, vector<vector<int>>& artifacts, vector<vector<int>>& dig) {
int ans = 0;
memset(remap,-1,sizeof remap);
int m = artifacts.size();
for(int i = 0;i < m; i ++)
{
dis[i] = cnt[i] = 0;
for(int x = artifacts[i][0]; x <= artifacts[i][2];x ++)
for(int y = artifacts[i][1];y <= artifacts[i][3];y ++)
{
remap[x][y] = i;
cnt[i] ++;
}
}
for(int i = 0; i < dig.size(); i ++)
{
int x = dig[i][0];
int y = dig[i][1];
if(remap[x][y] != -1)
{
int k = remap[x][y];
dis[k] ++;
remap[x][y] = -1;
if(dis[k] == cnt[k])ans ++;
}
}
return ans;
}
};