leetcode 5203. 统计可以提取的工件

5203. 统计可以提取的工件

这题刚开始以为模拟一下,最不济用一下二分,对于每一块地方,找到最先开始挖掘的下表,和最后结束的下标。注意这里面有重复元素,所以二分出来以后还需要判断.

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;      

    }
};

虽然没写出来,但是让我复习了二分。知道了二分如何找到第一个小于等于x的数。第二大于等于x的数,当二分时有重复元素怎么办

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值