[SHOI2008]堵塞的交通(线段数维护联通性)

Posted xu-daxia

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SHOI2008]堵塞的交通(线段数维护联通性)相关的知识,希望对你有一定的参考价值。

题目

2行c列个点,开始时互不联通,支持给同一列或着同一行相邻的两个点连边,和询问两个点能否在一个联通块里。

1≤C≤100000 1<=操作数<=100000;

题解

线段树的又一个骚操作。

我们把2*2的4个点看作线段树上的叶子结点。其他节点就是其儿子的合并(叶子结点的父亲表示2*4八个点,然后是2*8,2*16)。

然后在节点上维护节点表示的点的联通信息。

技术分享图片                                              技术分享图片

信息维护六种,就是用同种颜色连接的点是否联通。

所以信息合并时要写一堆。

然后发现这样叶子节点的信息不好修改(你写写就知道了),所以我们在叶子结点上额外记录实际连边的情况。

查询大体思路是把所有点分成三分,然后枚举所有情况。(假如两个点在同一列要特判)

技术分享图片

 

技术分享图片

 

 

技术分享图片

 

(这些线代表的是连通情况,并不是实际路线)

 然后就可以通过了

 

技术分享图片
  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 using namespace std;
  7 const int N=110010;
  8 int n;
  9 struct jz{
 10     int a[8];
 11 }hhh;
 12 struct tree{
 13     int l,r;
 14     jz z,tru; 
 15 }tr[N*8];
 16 void build(int l,int r,int now){
 17     tr[now].l=l;tr[now].r=r;
 18     if(l==r){
 19         return;
 20     }
 21     int mid=(tr[now].l+tr[now].r)>>1;
 22     build(l,mid,now*2);
 23     build(mid+1,r,now*2+1);
 24 }
 25 void update(int now){
 26     tr[now].z.a[2]=(tr[now*2].z.a[5]&tr[now*2+1].z.a[6])|(tr[now*2].z.a[2]&tr[now*2+1].z.a[2]);
 27     tr[now].z.a[4]=(tr[now*2].z.a[6]&tr[now*2+1].z.a[5])|(tr[now*2].z.a[4]&tr[now*2+1].z.a[4]);
 28     tr[now].z.a[5]=(tr[now*2].z.a[2]&tr[now*2+1].z.a[5])|(tr[now*2].z.a[5]&tr[now*2+1].z.a[4]);
 29     tr[now].z.a[6]=(tr[now*2].z.a[4]&tr[now*2+1].z.a[6])|(tr[now*2].z.a[6]&tr[now*2+1].z.a[2]);
 30     tr[now].z.a[1]=tr[now*2].z.a[1]|(tr[now*2].z.a[2]&tr[now*2].z.a[4]&tr[now*2+1].z.a[1]);
 31     tr[now].z.a[3]=tr[now*2+1].z.a[3]|(tr[now*2+1].z.a[2]&tr[now*2+1].z.a[4]&tr[now*2].z.a[3]);
 32 }
 33 void update(int x,int k,int c,int now){
 34     if(tr[now].l==tr[now].r){
 35         tr[now].tru.a[k]=c;
 36         for(int i=1;i<=6;i++){
 37             tr[now].z.a[i]=tr[now].tru.a[i];
 38         }
 39         tr[now].z.a[5]=(tr[now].tru.a[2]&tr[now].tru.a[3])|(tr[now].tru.a[1]&tr[now].tru.a[4]);
 40         tr[now].z.a[6]=(tr[now].tru.a[4]&tr[now].tru.a[3])|(tr[now].tru.a[1]&tr[now].tru.a[2]);
 41         tr[now].z.a[2]=tr[now].z.a[2]|(tr[now].z.a[5]&tr[now].z.a[3])|(tr[now].z.a[6]&tr[now].z.a[1]);
 42         tr[now].z.a[4]=tr[now].z.a[4]|(tr[now].z.a[5]&tr[now].z.a[1])|(tr[now].z.a[6]&tr[now].z.a[3]);
 43         tr[now].z.a[3]=tr[now].z.a[3]|(tr[now].z.a[5]&tr[now].z.a[2])|(tr[now].z.a[6]&tr[now].z.a[4]);
 44         tr[now].z.a[1]=tr[now].z.a[1]|(tr[now].z.a[5]&tr[now].z.a[4])|(tr[now].z.a[6]&tr[now].z.a[2]);
 45 //        for(int i=1;i<=6;i++){
 46 //            cout<<tr[now].z.a[i]<<" ";
 47 //        }
 48 //        cout<<endl;
 49         return;
 50     }
 51     int mid=(tr[now].l+tr[now].r)>>1;
 52     if(x<=mid)update(x,k,c,now*2);
 53     else update(x,k,c,now*2+1);
 54     update(now);
 55 }
 56 jz hb(jz a,jz b,jz c){
 57     c.a[2]=(a.a[5]&b.a[6])|(a.a[2]&b.a[2]);
 58     c.a[4]=(a.a[6]&b.a[5])|(a.a[4]&b.a[4]);
 59     c.a[5]=(a.a[2]&b.a[5])|(a.a[5]&b.a[4]);
 60     c.a[6]=(a.a[4]&b.a[6])|(a.a[6]&b.a[2]);
 61     c.a[1]=a.a[1]|(a.a[2]&a.a[4]&b.a[1]);
 62     c.a[3]=b.a[3]|(b.a[2]&b.a[4]&a.a[3]);
 63     return c;
 64 }
 65 jz check(int l,int r,int now){
 66     if(tr[now].l==l&&tr[now].r==r){
 67         return tr[now].z;
 68     }
 69     int mid=(tr[now].l+tr[now].r)>>1;
 70     if(l>mid)return check(l,r,now*2+1);
 71     else if(r<=mid)return check(l,r,now*2);
 72     else {
 73         return hb(check(l,mid,now*2),check(mid+1,r,now*2+1),hhh);
 74     }
 75 }
 76 int main(){
 77     scanf("%d",&n);
 78     build(1,n+2,1);
 79     string s;
 80     while(cin>>s){
 81         if(s[0]==E)break;
 82         int x1,y1,x2,y2;
 83         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
 84         if(y1>y2)swap(x2,x1),swap(y1,y2);
 85         if(s[0]==O){
 86             if(y1==y2){
 87                 update(y1,3,1,1);
 88                 update(y1+1,1,1,1); 
 89             }
 90             else {
 91                 if(x1==1)update(y1+1,2,1,1);
 92                 else update(y1+1,4,1,1);
 93             }
 94         }
 95         else if(s[0]==C){
 96             if(y1==y2){
 97                 update(y1,3,0,1);
 98                 update(y1+1,1,0,1); 
 99             }
100             else {
101                 if(x1==1)update(y1+1,2,0,1);
102                 else update(y1+1,4,0,1);
103             }
104         }
105         else {
106             if(y1==y2){
107                 jz x=check(1,y1,1);
108                 jz y=check(y1+1,n+1,1);
109                 if(x.a[3]|y.a[1])printf("Y
");
110                 else printf("N
");
111             }
112             else{    
113                 jz z=check(y1+1,y2,1);
114                 jz x=check(1,y1,1);
115                 jz y=check(y2+1,n+1,1);
116                 if(x1==x2){
117                     if(x1==1){
118                         if(z.a[2]|(x.a[3]&z.a[4]&y.a[1])|(x.a[3]&z.a[6])|(z.a[5]&y.a[1]))printf("Y
");
119                         else printf("N
");
120                     }
121                     else if(z.a[4]|(x.a[3]&z.a[2]&y.a[1])|(x.a[3]&z.a[5])|(z.a[6]&y.a[1]))printf("Y
");
122                          else printf("N
");
123                 }
124                 else{
125                     if(x1==1){
126                         if(z.a[5]|(x.a[3]&z.a[4])|(y.a[1]&z.a[2])|(x.a[3]&z.a[6]&y.a[1]))printf("Y
");
127                         else printf("N
");
128                     }
129                     else if(z.a[6]|(x.a[3]&z.a[2])|(y.a[1]&z.a[4])|(x.a[3]&z.a[5]&y.a[1]))printf("Y
");
130                          else printf("N
");
131                 }
132             }
133         }
134     }
135     return 0; 
136 }
View Code

 


以上是关于[SHOI2008]堵塞的交通(线段数维护联通性)的主要内容,如果未能解决你的问题,请参考以下文章

[SHOI2008]堵塞的交通

BZOJ1018[SHOI2008]堵塞的交通traffic(线段树)

bzoj1018:[SHOI2008]堵塞的交通traffic

bzoj1018 [SHOI2008]堵塞的交通traffic——线段树

[SHOI2008]堵塞的交通traffic

1018: [SHOI2008]堵塞的交通traffic