bzoj1018 [SHOI2008]堵塞的交通traffic

傳送門

噁心的線段樹。。。
吐槽:這題update真tm難寫……
線段樹維護連通性以前聽說過,但這一次是第一次寫,結果寫吐了。。
由於城市中道路是2行n列,所以我們可以在線段樹中維護左邊兩個點和右邊兩個點以及左邊兩個點之間和右邊兩個點之間的連通性。橫着的操作可以在線段樹遞歸到這條邊連接左右子樹的時候進行操作,豎着的操作可以在遞歸到葉子的時候將一對點看作兩對點,然後將其位於對角線上的兩對點以及左邊一對和右邊一對的連通性修改,其餘的注意update就行了。

CODE:

#include<cstdio>
#define N 100005
struct tree
{
    bool a[2][2];
    bool left,right;
    bool up,down;
}t[N<<2];
char str[10];
int n,x1,y1,x2,y2;
inline void swap(int &a,int &b){a^=b,b^=a,a^=b;}
inline bool getstring()
{
    char c=getchar();int p=0;
    while((c<'A'||c>'Z')&&(c<'a'||c>'z')) c=getchar();
    while((c>='A'&&c<='Z')||(c>='a'&&c<='z')) str[++p]=c,c=getchar();
    return str[1]!='E';
}
inline void update(tree &now,tree &s1,tree &s2)
{
    now.a[0][0]=(s1.a[0][0]&&now.up&&s2.a[0][0])||(s1.a[0][1]&&now.down&&s2.a[1][0]);
    now.a[0][1]=(s1.a[0][0]&&now.up&&s2.a[0][1])||(s1.a[0][1]&&now.down&&s2.a[1][1]);
    now.a[1][0]=(s1.a[1][0]&&now.up&&s2.a[0][0])||(s1.a[1][1]&&now.down&&s2.a[1][0]);
    now.a[1][1]=(s1.a[1][0]&&now.up&&s2.a[0][1])||(s1.a[1][1]&&now.down&&s2.a[1][1]);
    now.left =s1.left ||(s1.a[0][0]&&s1.right&&s1.a[1][1])||(s1.a[0][0]&&now.up&&s2.left &&now.down&&s1.a[1][1])||(s1.a[0][0]&&now.up&&s2.a[0][0]&&s2.right&&s2.a[1][1]&&now.down&&s1.a[1][1]);
    now.right=s2.right||(s2.a[0][0]&&s2.left &&s2.a[1][1])||(s2.a[0][0]&&now.up&&s1.right&&now.down&&s2.a[1][1])||(s2.a[0][0]&&now.up&&s1.a[0][0]&&s1.left &&s1.a[1][1]&&now.down&&s2.a[1][1]);
}
void build(int l,int r,int now)
{
    if(l==r)
    {
        t[now].a[0][0]=t[now].a[1][1]=1;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,now<<1);
    build(mid+1,r,now<<1|1);
}
void add1(int l,int r,int now,bool change)
{
    int mid=(l+r)>>1;
    if(y1==mid)
    {
        if(x1==1) t[now].up=change;
        else t[now].down=change;
        update(t[now],t[now<<1],t[now<<1|1]);
        return;
    }
    if(y1<mid) add1(l,mid,now<<1,change);
    else add1(mid+1,r,now<<1|1,change);
    update(t[now],t[now<<1],t[now<<1|1]);
}
void add2(int l,int r,int now,bool change)
{
    if(l==r)
    {
        t[now].a[0][1]=t[now].a[1][0]=change;
        t[now].left=t[now].right=change;
        return;
    }
    int mid=(l+r)>>1;
    if(y1<=mid) add2(l,mid,now<<1,change);
    else add2(mid+1,r,now<<1|1,change);
    update(t[now],t[now<<1],t[now<<1|1]);
}
tree ask(int L,int R,int l,int r,int now)
{
    if(L>R||L<0||R>n) return t[0];
    if(L<=l&&r<=R) return t[now];
    int mid=(l+r)>>1;
    if(R<=mid) return ask(L,R,l,mid,now<<1);
    if(L>mid) return ask(L,R,mid+1,r,now<<1|1);
    tree ans=t[now],tmp1,tmp2;
    tmp1=ask(L,R,l,mid,now<<1);
    tmp2=ask(L,R,mid+1,r,now<<1|1);
    update(ans,tmp1,tmp2);
    return ans;
}
inline void change(bool wh)
{
    if(x1==x2)
    {
        if(y1>y2) swap(y1,y2);
        return add1(1,n,1,wh);
    }
    if(x1>x2) swap(x1,x2);
    add2(1,n,1,wh);
}
inline bool Ask()
{
    if(y1>y2) swap(x1,x2),swap(y1,y2);
    tree mid=ask(y1,y2,1,n,1);
    int wh1=x1==1?0:1,wh2=x2==1?0:1;
    if(mid.a[wh1][wh2]) return 1;
    tree left=ask(1,y1-1,1,n,1),right=ask(y2+1,n,1,n,1);
    tree llink=ask(y1-1,y1,1,n,1),rlink=ask(y2,y2+1,1,n,1);
    if(!mid.left) mid.left=(llink.a[0][0]&&llink.a[1][1]&&left.right);
    if(!mid.right) mid.right=(rlink.a[0][0]&&rlink.a[1][1]&&right.left);
    if(!wh1&&!wh2) return mid.a[0][0]||(mid.left&&mid.a[1][1]&&mid.right);
    if(!wh1&&wh2) return (mid.a[0][0]&&mid.right)||(mid.left&&mid.a[1][1]);
    if(wh1&&!wh2) return (mid.left&&mid.a[0][0])||(mid.a[1][1]&&mid.right);
    return mid.a[1][1]||(mid.left&&mid.a[0][0]&&mid.right);
}
int main()
{
    scanf("%d",&n);
    build(1,n,1);
    while(getstring())
    {
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        if(str[1]=='O') change(1);
        else if(str[1]=='C') change(0);
        else if(Ask()) puts("Y");
        else puts("N");
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章