BZOJ 1018 线段树维护连通性

这个题我总是想用循环完成转移,最后发现,还是手工枚举最靠谱~

建立线段树,线段树的每个节点(代表的是区间)维护以上六个值,true表示连通,false表示不连通,具体可以看我的代码~

 

View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 
  7 #define N 111111
  8 
  9 using namespace std;
 10 
 11 struct DAT
 12 {
 13     bool v[2],s[2],x[2];
 14     void prt() {printf("s:%d      %d\nx:%d      %d\nv:%d      %d\n\n",s[0],s[1],x[0],x[1],v[0],v[1]);}
 15 }dat[N<<2];
 16 
 17 bool a[N][2][2];
 18 int n,r1,r2,c1,c2;
 19 int dx[3]={-1,0,1};
 20 int dy[3]={0,1,0};
 21 
 22 inline void build(int u,int l,int r)
 23 {
 24     if(l==r) {dat[u].s[0]=dat[u].s[1]=true;return;}
 25     int mid=(l+r)>>1;
 26     build(u<<1,l,mid); build(u<<1|1,mid+1,r);
 27 }
 28 
 29 inline void pack(DAT &u,DAT &ls,DAT &rs,int mid)
 30 {
 31     u.x[0]=ls.x[0]||(ls.s[0]&&a[mid][0][0]&&rs.x[0]&&a[mid][1][0]&&ls.s[1]);//左上-右上 
 32     u.x[1]=rs.x[1]||(rs.s[0]&&a[mid][0][0]&&ls.x[1]&&a[mid][1][0]&&rs.s[1]);//左下-右下 
 33     u.s[0]=(ls.s[0]&&a[mid][0][0]&&rs.s[0])||(ls.v[0]&&a[mid][1][0]&&rs.v[1]);//左上-左下
 34     u.s[1]=(ls.s[1]&&a[mid][1][0]&&rs.s[1])||(ls.v[1]&&a[mid][0][0]&&rs.v[0]);//右上-右下
 35     u.v[0]=(ls.s[0]&&a[mid][0][0]&&rs.v[0])||(ls.v[0]&&a[mid][1][0]&&rs.s[1]);//左上-右下
 36     u.v[1]=(ls.s[1]&&a[mid][1][0]&&rs.v[1])||(ls.v[1]&&a[mid][0][0]&&rs.s[0]);//右上-左下 
 37 }
 38 
 39 inline void updata(int u,int l,int r,int p)
 40 {
 41     if(l==r)
 42     {
 43         dat[u].x[0]=dat[u].x[1]=dat[u].v[1]=dat[u].v[0]=a[p][0][1];
 44         dat[u].s[0]=dat[u].s[1]=true;
 45         return;
 46     }
 47     int mid=(l+r)>>1;
 48     if(p<=mid) updata(u<<1,l,mid,p);
 49     else updata(u<<1|1,mid+1,r,p);
 50     pack(dat[u],dat[u<<1],dat[u<<1|1],mid);
 51 }
 52 
 53 inline void change(bool pd)
 54 {
 55     if(r1>r2) swap(r1,r2),swap(c1,c2);
 56     int dir;
 57     for(int i=0;i<3;i++)
 58         if(c1+dx[i]==c2&&r1+dy[i]==r2) dir=i;
 59     if(dir==0) a[c2][r2][0]=pd,updata(1,1,n,c2);
 60     else if(dir==1) a[c1][0][1]=pd,updata(1,1,n,c1);
 61     else a[c1][r1][0]=pd,updata(1,1,n,c1);
 62 }
 63 
 64 inline void getpack(DAT &p,int u,int L,int R,int l,int r)
 65 {
 66     if(l<=L&&r>=R) {p=dat[u];return;}
 67     int MID=(L+R)>>1;
 68     if(r<=MID) getpack(p,u<<1,L,MID,l,r);
 69     else if(l>=MID+1) getpack(p,u<<1|1,MID+1,R,l,r);
 70     else
 71     {
 72         DAT tmp1,tmp2;
 73         getpack(tmp1,u<<1,L,MID,l,MID);
 74         getpack(tmp2,u<<1|1,MID+1,R,MID+1,r);
 75         pack(p,tmp1,tmp2,MID);
 76     }
 77 }
 78 
 79 inline void getans()
 80 {
 81     if(c1>c2) swap(c1,c2),swap(r1,r2);
 82     DAT pa,pb,pc;
 83     getpack(pa,1,1,n,1,c1);
 84     getpack(pb,1,1,n,c1,c2);
 85     getpack(pc,1,1,n,c2,n);
 86     if(r1==r2)
 87     {
 88         if(r1==0)
 89         {
 90             if(pb.s[0]||(pa.x[1]&&pb.v[1])||(pc.x[0]&&pb.v[0])||(pa.x[1]&&pb.s[1]&&pc.x[0])) puts("Y");
 91             else puts("N");
 92         }
 93         else
 94         {
 95             if(pb.s[1]||(pa.x[1]&&pb.v[0])||(pc.x[0]&&pb.v[1])||(pa.x[1]&&pb.s[0]&&pc.x[0])) puts("Y");
 96             else puts("N");
 97         }
 98     }
 99     else
100     {
101         if(r1==0)
102         {
103             if(pb.v[0]||(pa.x[1]&&pb.s[1])||(pc.x[0]&&pb.s[0])) puts("Y");
104             else puts("N");
105         }
106         else
107         {
108             if(pb.v[1]||(pa.x[1]&&pb.s[0])||(pc.x[0]&&pb.s[1])) puts("Y");
109             else puts("N");
110         }
111     }
112 }
113 
114 inline void go()
115 {
116     char str[10];
117     scanf("%d",&n);
118     build(1,1,n);
119     while(scanf("%s",str))
120     {
121         if(str[0]=='E') break;
122         scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
123         r1--; r2--;
124         if(str[0]=='O') change(1);
125         else if(str[0]=='C') change(0);
126         else getans();
127     }
128 }
129 
130 int main()
131 {
132     go();
133     return 0;
134 }

 

感觉这个题还是挺神的~

 

 

posted @ 2013-03-12 23:10  proverbs  阅读(1526)  评论(2编辑  收藏  举报