[SHOI2008]堵塞的交通

Description

  有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个
城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,
直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度
发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通
部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:
Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了;Open r1 c1 r2 c2:相邻的两座城
市(r1,c1)和(r2,c2)之间的道路被疏通了;Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一
条路径使得这两条城市连通,则返回Y,否则返回N;

Input

  第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为
结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。

Output

  对于每个查询,输出一个“Y”或“N”。

Sample Input

2
Open 1 1 1 2
Open 1 2 2 2
Ask 1 1 2 2
Ask 2 1 2 2
Exit

Sample Output

Y
N
线段树中区间[l, r]存储(1, l)、(2, l)、(1, r)、(2, r)四个点两两间的连通性,总共有6种
合并:
区间合并的六种情况
横向边用2个数组ru和rd保存,用于合并,对于6个连通性,一一合并
修改:
修改横向边时,修改ru和rd数组,然后从下往上合并
修改纵向边时,修改该区间内四种状态,然后从下往上合并
查询:
优于可能存在这样的情况:
左右绕的示例
所以[1,c1],[c1,c2],[c2,n]的连通情况都要算出来
然后根据r1,r2判断就行了
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 struct Data
  8 {
  9   bool luru,lurd,luld,ldru,ldrd,rurd;
 10 }c[400001];
 11 bool ru[200001],rd[200001];
 12 int n;
 13 char s[21];
 14 Data merge(Data dl,Data dr,int mid)
 15 {
 16   Data dm;
 17   dm.luru=(dl.luru&ru[mid]&dr.luru)||(dl.lurd&rd[mid]&dr.ldru);
 18   dm.lurd=(dl.luru&ru[mid]&dr.lurd)||(dl.lurd&rd[mid]&dr.ldrd);
 19   dm.luld=(dl.luld)||(ru[mid]&&rd[mid]&&dl.luru&&dl.ldrd&&dr.luld);
 20   dm.ldru=(dl.ldru&&ru[mid]&&dr.luru)||(dl.ldrd&&rd[mid]&&dr.ldru);
 21   dm.ldrd=(dl.ldrd&&rd[mid]&&dr.ldrd)||(dl.ldru&&ru[mid]&&dr.lurd);
 22   dm.rurd=(dr.rurd)||(ru[mid]&&rd[mid]&&dr.luru&&dr.ldrd&&dl.rurd);
 23   return dm;
 24 }
 25 void update1(int rt,int l,int r,int x,bool up,bool k)
 26 {
 27   if (l==r)
 28     {
 29       if (up) ru[x]=k;
 30       else rd[x]=k;
 31       return;
 32     }
 33   int mid=(l+r)>>1;
 34   if (x<=mid) update1(rt<<1,l,mid,x,up,k);
 35   else update1(rt<<1|1,mid+1,r,x,up,k);
 36   c[rt]=merge(c[rt<<1],c[rt<<1|1],mid);
 37 }
 38 void update2(int rt,int l,int r,int x,bool k)
 39 {
 40   if (l==r)
 41     {
 42       c[rt].luld=c[rt].rurd=c[rt].lurd=c[rt].ldru=k;
 43       return;
 44     }
 45   int mid=(l+r)>>1;
 46   if (x<=mid) update2(rt<<1,l,mid,x,k);
 47   else update2(rt<<1|1,mid+1,r,x,k);
 48   c[rt]=merge(c[rt<<1],c[rt<<1|1],mid);
 49 }
 50 Data query(int rt,int l,int r,int L,int R)
 51 {
 52   if (l==L&&r==R)
 53     {
 54       return c[rt];
 55     }
 56   int mid=(l+r)>>1;
 57   if (L>mid) return query(rt<<1|1,mid+1,r,L,R);
 58   else if (R<=mid) return query(rt<<1,l,mid,L,R);
 59   else
 60     {
 61       return merge(query(rt<<1,l,mid,L,mid),query(rt<<1|1,mid+1,r,mid+1,R),mid);
 62     }
 63 }
 64 void build(int rt,int l,int r)
 65 {
 66   if (l==r)
 67     {
 68       c[rt].luru=1;c[rt].ldrd=1;
 69       return;
 70     }
 71   int mid=(l+r)>>1;
 72   build(rt<<1,l,mid);
 73   build(rt<<1|1,mid+1,r);
 74 }
 75 int main()
 76 {int i,r1,r2,c1,c2;
 77   cin>>n;
 78   build(1,1,n);
 79   for (i=1;i<n;i++)
 80     ru[i]=rd[i]=0;
 81   while (1)
 82     {
 83       scanf("%s",s);
 84       scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
 85       if (c1>c2) swap(c1,c2),swap(r1,r2);
 86       if (s[0]=='E') break;
 87       if (s[0]=='O')
 88     {
 89       if (r1==r2)
 90         update1(1,1,n,c1,r1==1,1);
 91       else update2(1,1,n,c2,1);
 92     }
 93       else if (s[0]=='C')
 94     {
 95       if (r1==r2)
 96         update1(1,1,n,c1,r1==1,0);
 97       else update2(1,1,n,c2,0);
 98     }
 99       else
100     {
101       Data dm=query(1,1,n,c1,c2),dl=query(1,1,n,1,c1),dr=query(1,1,n,c2,n);
102       if (r1==1&&r2==1)
103         {
104           bool b1=dm.luru;
105           bool b2=dl.rurd&dm.ldru;
106           bool b3=dm.lurd&dr.luld;
107           bool b4=dl.rurd&dm.ldrd&dr.luld;
108           if (b1||b2||b3||b4) printf("Y\n");
109           else printf("N\n");
110         }
111       else if (r1==2&&r2==2)
112         {
113           bool b1=dm.ldrd;
114           bool b2=dl.rurd&dm.lurd;
115           bool b3=dm.ldru&dr.luld;
116           bool b4=dl.rurd&dm.luru&dr.luld;
117           if (b1||b2||b3||b4) printf("Y\n");
118           else printf("N\n");
119         }
120       else if (r1==1&&r2==2)
121         {
122           bool b1=dm.lurd;
123           bool b2=dl.rurd&dm.ldrd;
124           bool b3=dm.luru&dr.luld;
125           bool b4=dl.rurd&dm.ldru&dr.luld;
126           if (b1||b2||b3||b4) printf("Y\n");
127           else printf("N\n");
128         }
129       else if (r1==2&&r2==1)
130         {
131           bool b1=dm.ldru;
132           bool b2=dl.rurd&dm.luru;
133           bool b3=dm.ldrd&dr.luld;
134           bool b4=dl.rurd&dm.lurd&dr.luld;
135           if (b1||b2||b3||b4) printf("Y\n");
136           else printf("N\n");
137         }
138     }
139     }
140 }

 

左右绕的示例

posted @ 2018-02-24 14:04  Z-Y-Y-S  阅读(251)  评论(0编辑  收藏  举报