BZOJ1018

来源:互联网 发布:雅马哈p115软件 编辑:程序博客网 时间:2024/05/29 19:21

这题难了我一B…
不过写过之后也就那样吧…
下面是题解:
由于只有两行,我们可以来棵线段树来维护联通性(四个结点的完全图).
每个结点储存该列与其右边列的联通性和该列本身的联通性,即结点[l,r]储存从第l列到第r+1列的联通关系(只考虑[l,r+1)之间的边,就是说不考虑r+1竖直方向的边).
这样,对于某列l的联通性,需要查询[1,l1]的结点和[l,c]的结点.
修改操作即为简单的单点修改,查询操作只需这样,假设所需查询区间为[l,r],对于其联通性,我们先求得l列,r列的连通性,再求得[l,r1]的联通性就可搞出结果.
细节可以查看代码(注意线段树的合并操作)
代码:

#include <bits/stdc++.h>using namespace std;const int MAXN=int(1e5+5);int n,s,t,v;int r1,c1,r2,c2;char op[10];int read(){    int r=0;char c;    while(!isdigit(c=getchar()));    while(r=r*10+c-'0',isdigit(c=getchar()));    return r;}#define aa sta[2][0]    //  x  ww  z#define dd sta[2][1]    //    |--|#define ww sta[0][0]    //  a |\/| d#define xx sta[0][1]    //  a |/\| d#define zz sta[1][0]    //    |--|#define ss sta[1][1]    //  z  ss  xstruct Sta{    bool sta[3][2];    Sta(){memset(sta,0,sizeof(sta));}    bool* operator [] (const int &x) {return sta[x];}    Sta operator + (const Sta &b) const {        Sta c;        c.aa=  aa ||   ww&&  ss&&b.aa;        c.dd=b.dd || b.ww&&b.ss&&  dd;        c.ss=ss&&b.ss || zz&&b.xx;        c.ww=ww&&b.ww || xx&&b.zz;        c.zz=ss&&b.zz || zz&&b.ww;        c.xx=ww&&b.xx || xx&&b.ss;        return c;    }//有些情况有重叠,不需重复考虑};struct SGT{    SGT *ls,*rs;    int l,r,mid;    Sta sta;    SGT(){};    SGT(int l,int r):ls(0),rs(0),l(l),r(r){}    void Build();    void Push_Up(){sta=ls->sta+rs->sta;}    Sta Query(){        if(s<=l && t>=r) return sta;        if(s<=mid && t>mid) return ls->Query()+rs->Query();        return s<=mid?ls->Query():rs->Query();    }void Updata(){        if(l==r){            if(r1!=r2) aa=v;            else r1?ss=v:ww=v;            zz=aa&&ww; xx=aa&&ss; dd=aa&&ww&&ss;            return;        }        s<=mid?ls->Updata():rs->Updata();        Push_Up();    }}*tree,Node[MAXN<<1];int cnt=0;SGT* New_Node(int l,int r){    Node[cnt]=SGT(l,r);    return &Node[cnt++];}void SGT::Build(){    if(l==r) return;    mid=(l+r)>>1;    (ls=New_Node(l,mid))->Build();    (rs=New_Node(mid+1,r))->Build();}bool Ask(){    bool f[2]={0};    c1>1?(s= 1,t=c1-1,f[0]=tree->Query().dd):0;          s=c2,t=   n,f[1]=tree->Query().aa;    if(c1==c2) return f[0]||f[1];    s=c1;t=c2-1;    Sta ans=tree->Query();    if(f[0]&&f[1]) return ans[0][0]||ans[1][0]||ans[0][1]||ans[1][1];    if(f[0]) return ans[0][r2]||ans[1][r2];    if(f[1]) return ans[r1][0]||ans[r1][1];    return ans[r1][r2];}int main(){#ifdef bhiaibogf    freopen("in.in","r",stdin);#endif    n=read();    (tree=New_Node(1,n))->Build();    for(;;){        scanf("%s",op);        if(op[0]=='E') return 0;        r1=read();c1=read();r2=read();c2=read();        r1--;r2--;        if(c1>c2) swap(c1,c2),swap(r1,r2);        switch (op[0]){            case 'O':v=1;s=c1;tree->Updata(); break;            case 'C':v=0;s=c1;tree->Updata(); break;            case 'A':puts(c1==c2&&r1==r2 || Ask()?"Y":"N"); break;        }    }    return 0;}
0 0