zoukankan      html  css  js  c++  java
  • POJ 2109 Inner Vertices(扫描线+树状数组)

    【题目链接】 http://poj.org/problem?id=3109

    【题目大意】

      在一个棋盘上放满白子,现在把一些白子变成黑子,
      如果一个白子上下左右都有黑子,就会变成黑子,问最终黑子个数

    【题解】

      首先我们在每列的开头和结尾做标记,之后对行线扫描,
      如果是列的开头,那么在该列中标记,如果是列的结尾,则在该列中去除标记
      那么我们只要统计行的开头到行的结尾之间夹着多少列标记,且该列下该行没有原来的黑子
      就是该行新增的黑子数量,对于总的黑子数量,可以用树状数组统计,之后容斥一下列标记即可。

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <utility>
    #define cx first
    #define cy second
    using namespace std;
    typedef long long LL; 
    const int MAX_N=100010;
    typedef pair<int,int> P;
    int t,c[MAX_N],r[MAX_N],N,ys[MAX_N],d[MAX_N],vis[MAX_N];
    P p[MAX_N];
    bool cmp(int a,int b){return p[a].cy<p[b].cy||p[a].cy==p[b].cy&&p[a].cx<p[b].cx;}
    int sum(int x){int s=0;while(x)s+=c[x],x-=(x&-x);return s;}
    void add(int x,int v){while(x<=t)c[x]+=v,x+=x&-x;}
    int main(){
        scanf("%d",&N);
        for(int i=0;i<N;i++)scanf("%d%d",&p[i].cx,&p[i].cy),r[i]=i;
        sort(p,p+N); sort(r,r+N,cmp);
        ys[r[0]]=1; d[r[0]]=1;
        for(int i=1;i<N;i++){
            ys[r[i]]=ys[r[i-1]];
            if(p[r[i]].cy==p[r[i-1]].cy)continue;
            d[r[i-1]]--; d[r[i]]++;
            ys[r[i]]++;
        }LL ans=N; d[r[N-1]]--; t=ys[r[N-1]];
        for(int i=0,j=0;i<N;){
            for(j=i;j<N&&p[j].cx==p[i].cx;j++)
                if(d[j]<0){vis[ys[j]]=0;add(ys[j],-1);}
            if(ys[i]<ys[j-1]-1){
                ans+=sum(ys[j-1]-1)-sum(ys[i]);
                for(int k=i+1;k<j-1;k++)if(vis[ys[k]])ans--;
            }for(;i<j;i++)if(d[i]>0){add(ys[i],1);vis[ys[i]]=1;}
        }printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    django LDAP
    Python egg
    皮皮书屋
    Linux运维
    bash shell 快捷键汇总
    linux ldconfig
    Linux set env export declare unset
    OpenStack
    【LeetCode】258. Add Digits
    一个"Median Maintenance"问题
  • 原文地址:https://www.cnblogs.com/forever97/p/poj2109.html
Copyright © 2011-2022 走看看