[ 线段树 网络流 ] Codeforces793G Oleg and chess

来源:互联网 发布:sql存储过程详细教学 编辑:程序博客网 时间:2024/06/06 20:44

我们可以通过扫描线将网格图分成 O(n) 个矩形。然后对行、列分别建一棵线段树。对于每个矩形,建一个中间点,将行、列与它分别连边,边数为 O(nlogn)

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define N 10010#define M 400000#define INF 1e9inline char nc(){    static char buf[100000],*p1=buf,*p2=buf;    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void Read(int& x){    char c=nc();    for(;c<'0'||c>'9';c=nc());    for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());}struct Node{    int x,l,r;    int f;    Node(int x=0,int l=0,int r=0,int f=0):x(x),l(l),r(r),f(f){}}c[N<<1];struct Edge{    int t,nx,c;}e[3000000];int h[M],d[M],q[M],cur[M];bool b[M];int i,j,k,n,m,p,a[N];int x1,x2,y1,y2,s,t,cnt;int num=1,r1,r2,ls[N<<3],rs[N<<3];inline void Add(int x,int y,int z){    e[++num].t=y;e[num].c=z;e[num].nx=h[x];h[x]=num;    e[++num].t=x;e[num].c=0;e[num].nx=h[y];h[y]=num;}inline void Build(int& x,int y,int l,int r,int d){    x=++cnt;    if(y){        if(!d)Add(x,y,INF);else Add(y,x,INF);    }    if(l==r)return;    int Mid=l+r>>1;    Build(ls[x],x,l,Mid,d);Build(rs[x],x,Mid+1,r,d);}inline void Build2(int x,int l,int r,int y){    if(l==r){        if(!y)Add(0,x,1);else Add(x,t,1);        return;    }    int Mid=l+r>>1;    Build2(ls[x],l,Mid,y);Build2(rs[x],Mid+1,r,y);}inline bool Cmp(Node a,Node b){    if(a.x==b.x)return a.f>b.f;    return a.x<b.x;}inline void Query(int x,int l,int r,int L,int R,int y,bool d){    if(!x||l>R||r<L)return;    if(l>=L&&r<=R){        if(!d)Add(x,y,INF);else Add(y,x,INF);        return;    }    int Mid=l+r>>1;    Query(ls[x],l,Mid,L,R,y,d);    Query(rs[x],Mid+1,r,L,R,y,d);}inline void Insert(int x,int l,int r){    int pos=-1,last=-1,y;    for(int i=l;i<=r+1;i++){        if(i<=r)y=a[i]+1,a[i]=-1;        if(y!=last||i==r+1){            if(pos!=-1){                int z=++cnt;                Query(r1,1,n,pos,i-1,z,0);                Query(r2,1,n,last,x,z,1);            }            pos=i;last=y;        }    }}inline void Modify(int x,int l,int r){    for(int i=l;i<=r;i++)a[i]=x;}inline bool Bfs(){    memset(b,0,sizeof(b));    b[s]=1;int l=0,r=1;q[1]=s;    while(++l<=r){        int x=q[l];        for(int i=h[x];i;i=e[i].nx)        if(e[i].c&&!b[e[i].t]){            b[e[i].t]=1;d[e[i].t]=d[x]+1;q[++r]=e[i].t;        }    }    return b[t];}inline int Dfs(int x,int y){    if(!y||x==t)return y;    int k=y,f;    for(int& i=cur[x];i;i=e[i].nx){        int v=e[i].t;        if(d[v]==d[x]+1&&(f=Dfs(v,min(y,e[i].c)))){            y-=f;e[i].c-=f;e[i^1].c+=f;            if(!y)break;        }    }    if(k==y)d[x]=-1;    return k-y;}inline int Dinic(){    int Ans=0;    while(Bfs()){        for(int i=0;i<=cnt;i++)cur[i]=h[i];        Ans+=Dfs(s,INF);    }    return Ans;}int main(){    Read(n);Read(m);    Build(r1,0,1,n,0);Build(r2,0,1,n,1);    for(i=1;i<=m;i++){        Read(x1);Read(y1);Read(x2);Read(y2);        c[i*2-1]=Node(x1-1,y1,y2,0);c[i*2]=Node(x2,y1,y2,1);    }    sort(c+1,c+m*2+1,Cmp);    for(i=1;i<=m*2;i++)    if(!c[i].f)Insert(c[i].x,c[i].l,c[i].r);else Modify(c[i].x,c[i].l,c[i].r);    Insert(n,1,n);    t=++cnt;    Build2(r1,1,n,s);Build2(r2,1,n,t);    printf("%d\n",Dinic());    return 0;}
原创粉丝点击