首页 > 代码库 > BZOJ 1018 线段树维护图的连通性问题

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);        }    }}

 

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