zoukankan      html  css  js  c++  java
  • [CQOI2010] 内部白点

    题意:

    一个无穷大的网格图,初始时有n个黑点。每一个时刻,若点$(x,y)$满足:

    • $exist x1<x<x2$使得$(x1,y),(x2,y)$都是黑点。
    • $exist y1<x<y2$使得$(x,y1),(x,y2)$都是黑点。

    则点$(x,y)$也会变成黑点,求最终黑点数目,若一直变化输出-1。

    $nleq 10^{5},|x|,|y|leq 10^9$。

    题解:

    一开始把题里这两个条件读成“或者”而不是“而且”了,导致不会做,然后重新读了一遍发现是sb题。

    注意到一行或一列只有极大/极小值有用,而新加的黑点肯定不会是极大/极小值,那么实际上只会加一次或者一次都不加。

    然后就是个弱化版二维偏序,直接树状数组即可。

    复杂度$O(nlog{n})$。

    套路:

    • 维护不了多次变化的题$ ightarrow$考虑一下是不是只能变一次的诈骗题。

    代码:

    #include<bits/stdc++.h>
    #define maxn 500005
    #define maxm 500005
    #define inf 0x7fffffff
    #define ll long long
    #define rint register int
    #define debug(x) cerr<<#x<<": "<<x<<endl
    #define fgx cerr<<"--------------"<<endl
    #define dgx cerr<<"=============="<<endl
    
    using namespace std;
    struct node{int x,y;}P[maxn];
    int B[maxn],C[maxn],vis[maxn];
    vector<int> L[maxn];
    
    inline int read(){
        int x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    
    inline int lowbit(int x){return x&(-x);}
    inline void add(int x,int y,int n){for(int i=x;i<=n;i+=lowbit(i))C[i]+=y;}
    inline int qry(int x){int r=0;for(int i=x;i;i-=lowbit(i))r+=C[i];return r;}
    
    int main(){
        int n=read(),tot=0;
        for(int i=1;i<=n;i++){
            P[i].x=read(),P[i].y=read();
            B[++tot]=P[i].x,B[++tot]=P[i].y;
        }
        sort(B+1,B+1+tot);
        for(int i=1;i<=n;i++){
            P[i].x=lower_bound(B+1,B+1+tot,P[i].x)-B;
            P[i].y=lower_bound(B+1,B+1+tot,P[i].y)-B;
            L[P[i].x].push_back(P[i].y);
            //cout<<P[i].x<<" "<<P[i].y<<endl; 
        }
        int ans=0;
        for(int x=1;x<=tot;x++){
            if(!L[x].size()) continue;
            sort(L[x].begin(),L[x].end());
            for(int j=0;j<L[x].size();j++){
                int y=L[x][j],res=qry(y); 
                if(vis[y]) ans+=res; else vis[y]=1;
                add(y,-res,tot),add(y+1,res,tot);
            }
            for(int j=0;j<L[x].size()-1;j++){
                int y1=L[x][j]+1,y2=L[x][j+1]-1;
                if(y1<=y2) add(y1,1,tot),add(y2+1,-1,tot);
            }
        }
        printf("%d
    ",ans+n);
        return 0;
    }
    内部白点
  • 相关阅读:
    [原创]Android插件化的一种实现
    [原创]HierarchyView的实现原理和Android设备无法使用HierarchyView的解决方法
    使用linux mint 安装无线网卡驱动
    Ubuntu下U盘变成只读的解决方法
    在Android源码中查找Java代码中native函数对应的C++实现
    Android Training Caching Bitmaps 翻译
    [转]获取app的内部储存路径
    [转]sudo找不到命令:修改sudo的PATH路径
    [转]CDN(内容分发网络)技术原理
    电视的应用开发注意事项[持续更新]
  • 原文地址:https://www.cnblogs.com/YSFAC/p/13362996.html
Copyright © 2011-2022 走看看