• UVALive 7141 BombX


    离散化,线段树。$2014$年$ACM/ICPC$亚洲区域赛上海站$D$题。

    可以处理出炸任意相邻的$h$行能消灭的点的数量,以及炸任意相邻的$w$列能消灭的点的数量,分别用$py[i]$和$px[i]$记。

    然后可以枚举炸哪个相邻的$h$行,这相邻的$h$行中有些位置可能有点在,所以有一些位置的$px$值是不可取的,要将这些$px$删去之后找一个最大值$m$,利用$m+py[i]$更新答案。一个点会导致一段连续的$px$不可取,所以可以用线段树区间更新将这一段区间的值减去一个比$n$大的值,使得这一段区间的值都是负的。

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    
    const int maxn=3e5+10;
    int n,w,h;
    struct Point
    {
        int x,y;
        void read() { scanf("%d%d",&x,&y); }
    }p[maxn];
    vector<int>x,y,in[maxn],out[maxn];
    int px[maxn],py[maxn],W,H,ans;
    
    long long s[maxn*4],f[maxn*4];
    
    void build(int l,int r,int rt)
    {
        f[rt]=0;
        if(l==r) { s[rt]=px[l]; return ; }
    
        int m=(l+r)/2;
        build(l,m,2*rt);
        build(m+1,r,2*rt+1);
    
        s[rt]=max(s[2*rt],s[2*rt+1]);
    }
    
    void pushDown(int rt)
    {
        if(f[rt]==0) return ;
    
        s[2*rt]+=f[rt], f[2*rt]+=f[rt];
        s[2*rt+1]+=f[rt], f[2*rt+1]+=f[rt];
        f[rt]=0;
    }
    
    void update(int L,int R,int val,int l,int r,int rt)
    {
        if(L<=l&&r<=R) { s[rt]+=val, f[rt]+=val; return ; }
    
        int m=(l+r)/2;
        pushDown(rt);
    
        if(L<=m) update(L,R,val,l,m,2*rt);
        if(R>m) update(L,R,val,m+1,r,2*rt+1);
    
        s[rt]=max(s[2*rt],s[2*rt+1]);
    }
    
    int get(int g,bool flag)
    {
        if(flag==0) return lower_bound(x.begin(),x.end(),g)-x.begin()+1;
        return lower_bound(y.begin(),y.end(),g)-y.begin()+1;
    }
    
    int main()
    {
        int T,cas=1; scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d%d",&n,&w,&h);
            for(int i=1;i<=n;i++) p[i].read();  x.clear(); y.clear();
            for(int i=1;i<=n;i++)
            {
                y.push_back(p[i].y); y.push_back(p[i].y-h+1); y.push_back(p[i].y+1);
                x.push_back(p[i].x); x.push_back(p[i].x-w+1); x.push_back(p[i].x+1);
            }
            sort(x.begin(),x.end()); x.erase(unique(x.begin(),x.end()),x.end());
            sort(y.begin(),y.end()); y.erase(unique(y.begin(),y.end()),y.end());
    
            memset(px,0,sizeof px); memset(py,0,sizeof py);
    
            W=x.size(); H=y.size();
            for(int i=1;i<=H;i++) { in[i].clear(); out[i].clear(); }
    
            for(int i=1;i<=n;i++)
            {
                int xx=get(p[i].x-w+1,0), yy=get(p[i].y-h+1,1);
                int xxx=get(p[i].x+1,0), yyy=get(p[i].y+1,1);
                px[xx]++; px[xxx]--; py[yy]++; py[yyy]--;
                in[yy].push_back(i); out[yyy-1].push_back(i);
            }
    
            ans=0;
            for(int i=1;i<=W;i++) px[i]=px[i]+px[i-1], ans=max(ans,px[i]);
            for(int i=1;i<=H;i++) py[i]=py[i]+py[i-1], ans=max(ans,py[i]);
    
            build(1,W,1);
    
            for(int i=1;i<=H;i++)
            {
                for(int j=0;j<in[i].size();j++)
                {
                    int ll=get(p[in[i][j]].x-w+1,0), rr=get(p[in[i][j]].x,0);
                    update(ll,rr,-n,1,W,1);
                }
    
                if(s[1]>0) ans=max(ans,py[i]+(int)s[1]);
    
                for(int j=0;j<out[i].size();j++)
                {
                    int ll=get(p[out[i][j]].x-w+1,0), rr=get(p[out[i][j]].x,0);
                    update(ll,rr,n,1,W,1);
                }
            }
            printf("Case #%d: %d
    ",cas++,ans);
        }
        return 0;
    }
  • 相关阅读:
    POJ 1236 Network of Schools(强连通分量缩点求根节点和叶子节点的个数)
    文本编辑器vim和gedit
    Ubuntu安装tensorflow
    剑指offer——python【第29题】最小的K个数
    剑指offer——python【第30题】连续子数组的最大和
    剑指offer——python【第37题】数字在排序数组中出现的次数
    剑指offer——python【第28题】数组 中出现次数超过一半的数字
    剑指offer——python【第31题】整数1出现的次数
    剑指offer——python【第54题】字符流中第一个不重复的字符
    剑指offer——python【第40题】数组中只出现一次的数字
  • 原文地址:https://www.cnblogs.com/zufezzt/p/6001593.html
Copyright © 2020-2023  润新知