题目链接:http://codeforces.com/contest/1293/problem/C
题目:给定一个 2*n的地图,初始地图没有岩浆,都可以走,
给定q个询问,每个询问给定一个点(x,y),每个询问有以下作用:
(1)如果该点可走,则变为不可走
(2)如果该点不可走,则变为可走
问,每个询问作用后,还能否从(1,1)走到(2,n)。
思路:我们可以这么想:
如果第二层有个无法走的点,那么只要该点上方三个点任意一个点不可走,则该地图无法走到终点。
"如果第二层有个无法走的点,那么只要该点上方三个点任意一个点不可走"这句话可以想成该点会对上面
三个点贡献1点,那么第一层任意点的贡献值为[0,3],只要第一层有个点不可走,且第二层给它的贡献值不为0,
即该地图无法走通。如果第二层不能走的点变为可走了,那么对上面三个点的贡献度为-1,即减去之前的1点贡献。
下面用到了二维转一维来操作。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <queue> 5 using namespace std; 6 7 const int N = (int)3e5+100; 8 int app[N << 1];//该点障碍(岩浆)本来是否存在 9 int tot[N];//第一层的贡献度 10 int sum[10];//贡献度为1,2,3的点数 11 12 int main(){ 13 14 int n,q; 15 scanf("%d%d",&n,&q); 16 int x,y; 17 while(q--){ 18 scanf("%d%d",&x,&y); 19 if(x > 1){ //第二层 20 if(!app[ n+y ]){//第二层该点本来不存在 21 app[ n+y ] = 1;//标记存在 22 for(int now = max(1,(x-1)*y-1); now <= min((x-1)*y+1,n); ++now){ 23 if(app[now]){//第一层存在 24 //改变该点的贡献度,随之也要改变贡献度为1,2,3的点数的数量 25 --sum[tot[now]]; 26 ++tot[now]; 27 ++sum[tot[now]]; 28 } 29 else ++tot[now]; 30 } 31 }else{ 32 app[ n+y ] = 0; 33 for(int now = max(1,(x-1)*y-1); now <= min((x-1)*y+1,n); ++now){ 34 if(app[now]){//第一层存在 35 --sum[tot[now]]; 36 --tot[now]; 37 ++sum[tot[now]]; 38 } 39 else --tot[now]; 40 } 41 } 42 }else{//第一层的点,要判断第一层的点是否存在,如果第一层的该点不存在, 43 //第二层的贡献度对该点也没有影响 44 if(app[x*y]){ 45 app[x*y] = 0; 46 --sum[tot[x*y]]; 47 } 48 else{ 49 app[x*y] = 1; 50 ++sum[tot[x*y]]; 51 } 52 } 53 if(sum[1]+sum[2]+sum[3]) printf("%d__________________________No ",sum[1]+sum[2]+sum[3]); 54 else printf("__________________________Yes "); 55 } 56 57 return 0; 58 }