BZOJ 1018 线段树维护图的连通性问题

思路:

我们可以搞一棵线段树

对于一段区间有6种情况需要讨论

左上右下、左上右上、左下右下、左下右上

这四种比较好维护

用左上右下举个例子吧

就是左儿子的左上右下&左区间到右区间下面有路&右儿子的左下右下

或者是左儿子的左上右上&左区间到右区间上面有路&右儿子的左上右下

 

还有两种  区间的左(右)端点上下能不能联通 需要维护

这种就是左儿子的上下连通或(左上右上&左上右下&左到右两条路都联通&右儿子的上下联通)

(假设c1<c2)

最后要查的是 1->c1 (可以1~c1上下联通再c1[!r1]->c2)

c1->c2(直接联通当然最好)

c2->cn

还有一种是1~c1上下联通&c2~n上下联通&c1[!r1]与c2[!r2]上下联通

4种分类讨论即可

//By SiriusRen
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=100050;
int map[N][2],map2[N],n,r1,c1,r2,c2,jy;
char op[15];
struct Node{bool b[2][2],c[2];}tree[N*16];
Node push_up(Node L,Node R,int mid){
    Node tmp;
    tmp.b[0][0]=(L.b[0][0]&map[mid][0]&R.b[0][0])|(L.b[0][1]&map[mid][1]&R.b[1][0]);
    tmp.b[0][1]=(L.b[0][0]&map[mid][0]&R.b[0][1])|(L.b[0][1]&map[mid][1]&R.b[1][1]);
    tmp.b[1][0]=(L.b[1][0]&map[mid][0]&R.b[0][0])|(L.b[1][1]&map[mid][1]&R.b[1][0]);
    tmp.b[1][1]=(L.b[1][0]&map[mid][0]&R.b[0][1])|(L.b[1][1]&map[mid][1]&R.b[1][1]);
    tmp.c[0]=L.c[0]|(L.b[0][0]&map[mid][0]&map[mid][1]&L.b[1][1]&R.c[0]);
    tmp.c[1]=R.c[1]|(R.b[0][0]&map[mid][0]&map[mid][1]&R.b[1][1]&L.c[1]);
    return tmp;
}
void build(int l,int r,int pos){
    if(l==r){tree[pos].b[1][1]=tree[pos].b[0][0]=1;return;}
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    build(l,mid,lson),build(mid+1,r,rson);
}
void insert(int l,int r,int pos,int L,int num,bool v){
    if(l==r){
        if(num==2)tree[pos].b[0][1]=tree[pos].b[1][0]=tree[pos].c[0]=tree[pos].c[1]=map2[l]=v;
        else map[l][num]=v;return;
    }
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid<L)insert(mid+1,r,rson,L,num,v);
    else insert(l,mid,lson,L,num,v);
    tree[pos]=push_up(tree[lson],tree[rson],mid);
}
Node query(int l,int r,int pos,int L,int R){
    if(l>=L&&r<=R)return tree[pos];
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid<L)return query(mid+1,r,rson,L,R);
    else if(mid>=R)return query(l,mid,lson,L,R);
    else return push_up(query(l,mid,lson,L,R),query(mid+1,r,rson,L,R),mid);
}
int main(){
    scanf("%d",&n),build(1,n,1);
    while(scanf("%s",op)&&op[0]!='E'){
        scanf("%d%d%d%d",&r1,&c1,&r2,&c2),r1--,r2--;
        if(c1>c2)swap(c1,c2),swap(r1,r2);
        if(op[0]=='A'){
            Node a=query(1,n,1,1,c1),b=query(1,n,1,c2,n),c=query(1,n,1,c1,c2);
            if(c.b[r1][r2]|(a.c[1]&c.b[!r1][r2])|(b.c[0]&c.b[r1][!r2])|(b.c[0]&a.c[1]&c.b[!r1][!r2]))puts("Y");
            else puts("N");
        }
        else{
            if(r1==r2)jy=(r1==1);
            else jy=2;
            insert(1,n,1,c1,jy,op[0]=='O');
        }
    }
}

 

posted @ 2017-03-12 08:56  SiriusRen  阅读(315)  评论(0编辑  收藏  举报