吐槽
一道很简单的题,但是我的思路偏了,没写出来,一开始看到,就想到了
bfs()
,感觉完全没问题,其实算了一下时间复杂度,感觉会TLE,但是我依然倔强,想着对bfs()
进行一波剪枝,可以过,没想到还是TLE,赛后想到了正解,不过感觉自己代码能力有提升,现在想到一些东西,可以实现。
正解:
如果要把某个点翻成岩浆,那么我们就判断它的上位置或者下位置的三个点存在几个,然后
cnt
加上,若要把某个点翻成平路,我们就判断它的上位置或者下位置的三个点存在几个,然后cnt
减去,如果cnt>0
,输出No
,否则输出Yes
即可。
TLE代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn =1e5+5;
int mp[3][maxn];
int vis[3][10005];
int n,q;
struct node
{
int x,y;
} st,en;
int dir[3][2]= {0,1,1,0,-1,0};
queue<node>Q;
bool bfs(int i,int j)
{
while(!Q.empty())
Q.pop();
st.x=i;
st.y=j;
Q.push(st);
while(!Q.empty())
{
st=Q.front();
Q.pop();
if(st.x==2&&st.y==n)
{
return true;
}
for(int i=0; i<3; i++)
{
en.x=st.x+dir[i][0];
en.y=st.y+dir[i][1];
if((mp[1][en.y]&&mp[2][en.y])||(mp[1][en.y]&&mp[2][en.y+1])||(mp[1][en.y+1]&&mp[2][en.y]))
{
return false;
}
if(vis[en.x][en.y]||en.x>=3||en.x<=0||en.y<=0||en.y>n||mp[en.x][en.y])
continue;
vis[en.x][en.y]=1;
Q.push(en);
}
}
return false;
}
int main()
{
scanf("%d %d",&n,&q);
//int r1=0,r2=0;
while(q--)
{
int r,c;
memset(vis,0,sizeof(vis));
scanf("%d %d",&r,&c);
if(mp[r][c])
{
mp[r][c]=0;
}
else
{
mp[r][c]=1;
}
//vis[1][1]=1;
if(bfs(1,1))
{
printf("Yes\n");
}
else
{
printf("No\n");
}
}
}
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int mp[3][maxn];
int dir[3][2]= {-1,-1,-1,0,-1,1};
int dix[3][2]= {1,-1,1,0,1,1};
int cnt;
int r,c,n,q;;
void dirs(int x)
{
for(int i=0; i<3; i++)
{
int rx=dir[i][0]+r;
int cx=dir[i][1]+c;
if(rx<=0||rx>=3||cx<=0||cx>n)
{
continue;
}
if(mp[rx][cx]&&x)
{
cnt--;
}
else if(mp[rx][cx]&&!x)
{
cnt++;
}
}
}
void dixs(int x)
{
for(int i=0; i<3; i++)
{
int rx=dix[i][0]+r;
int cx=dix[i][1]+c;
if(rx<=0||rx>=3||cx<=0||cx>n)
{
continue;
}
if(mp[rx][cx]&&x)
{
cnt--;
}
else if(mp[rx][cx]&&!x)
{
cnt++;
}
}
}
int main()
{
scanf("%d %d",&n,&q);
while(q--)
{
scanf("%d %d",&r,&c);
if(mp[r][c])
{
if(r==2)
{
dirs(mp[r][c]);
}
else
{
dixs(mp[r][c]);
}
}
else
{
if(r==2)
{
dirs(mp[r][c]);
}
else
{
dixs(mp[r][c]);
}
}
mp[r][c]^=1;
if(cnt>0)
{
printf("No\n");
}
else
{
printf("Yes\n");
}
}
}