Codeforces Round #641 (Div. 2) E. Orac and Game of Life
题意
给定一张\(n\times m\)的\(01\)图
对于每个位置\((x,y)\)
-
如果相邻位置\((x-1,y),(x+1,y),(x,y-1),(x,y+1)\)的字符与其全部不同,则每次操作后在位置\((x,y)\)的字符不变
-
如果相邻位置的字符与其至少有一个相同,则每次操作后在位置\((x,y)\)的字符会相互改变
有\(T\)组询问,每次询问在\(p\)次操作后位置\((x,y)\)的字符是什么
限制
\(1\leq n,m\leq 1000\)
\(1\leq T\leq 100000\)
\(1\leq i\leq n, 1\leq j\leq m, 1\leq p\leq 10^{18}\)
思路
由题意可得,对于某个元素个数\(\gt 1\)的连通块,在每次操作之后都会使得与其相邻的(不同)字符发生改变
除非全图为全部\(01\)间隔,这种情况下每个字符都不会发生改变;
否则,在进行足够多次数的操作后,每次执行每个位置的字符都会发生改变
可以理解为,每个元素个数\(\gt 1\)的连通块都会在每次操作后向周围进行扩散,使得扩散到达的位置开始改变
如果某个位置还没有被扩散到,则不会发生改变;否则没执行一次就会改变一次
换言之,就是求出每个点到离自己最近的元素个数\(\gt 1\)的连通块的最短距离\(dis\)
如果询问的操作次数\(p\leq dis\),则说明还没有扩散到这个位置,字符还没有改变
否则,通过判断\(dis-p\)的奇偶性来确定指定位置的字符此时是什么,偶数相同奇数不同
直接多源BFS一遍即可
程序
(124ms/2000ms)
/*
* Author : StelaYuri
* Language : GNU G++ 14
*/
//#pragma comment(linker,"/STACK:1024000000,1024000000")
//#pragma GCC optimize(3)
#include<bits/stdc++.h>
//#include<unordered_map>
//#include<ext/pb_ds/assoc_container.hpp>
//#include<ext/pb_ds/hash_policy.hpp>
#define closeSync ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)
#define multiCase int T;cin>>T;for(int t=1;t<=T;t++)
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define repp(i,a,b) for(int i=(a);i<(b);i++)
#define per(i,a,b) for(int i=(a);i>=(b);i--)
#define perr(i,a,b) for(int i=(a);i>(b);i--)
#define pb push_back
#define eb emplace_back
#define mst(a,b) memset(a,b,sizeof(a))
using namespace std;
//using namespace __gnu_pbds;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> P;
const int INF=0x3f3f3f3f;
const ll LINF=0x3f3f3f3f3f3f3f3f;
const double eps=1e-12;
const double PI=acos(-1.0);
const double angcst=PI/180.0;
const ll mod=998244353;
ll max_3(ll a,ll b,ll c){if(a>b&&a>c)return a;if(b>c)return b;return c;}
ll min_3(ll a,ll b,ll c){if(a<b&&a<c)return a;if(b<c)return b;return c;}
ll gcd(ll a,ll b){return b==0?a:gcd(b,a%b);}
ll qmul(ll a,ll b){ll r=0;while(b){if(b&1)r=(r+a)%mod;b>>=1;a=(a+a)%mod;}return r;}
ll qpow(ll a,ll n){ll r=1;while(n){if(n&1)r=(r*a)%mod;n>>=1;a=(a*a)%mod;}return r;}
ll qpow(ll a,ll n,ll p){ll r=1;while(n){if(n&1)r=(r*a)%p;n>>=1;a=(a*a)%p;}return r;}
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
int n,m,t;
char mp[1050][1050];
int dis[1050][1050];
inline bool prim(int x,int y)
{
return x>0&&y>0&&x<=n&&y<=m;
}
void solve()
{
mst(dis,INF);
cin>>n>>m>>t;
rep(i,1,n)
cin>>mp[i]+1;
queue<P> q;
rep(i,1,n)
rep(j,1,m)
{
if(prim(i-1,j)&&mp[i][j]==mp[i-1][j]||
prim(i+1,j)&&mp[i][j]==mp[i+1][j]||
prim(i,j-1)&&mp[i][j]==mp[i][j-1]||
prim(i,j+1)&&mp[i][j]==mp[i][j+1])
{
dis[i][j]=0;
q.push(P(i,j));
}
}
bool flag=false;
if(q.empty())
flag=true;
while(!q.empty())
{
P pd=q.front();
q.pop();
rep(i,0,3)
{
int px=pd.first+dx[i],py=pd.second+dy[i];
if(prim(px,py)&&dis[px][py]>dis[pd.first][pd.second]+1)
{
dis[px][py]=dis[pd.first][pd.second]+1;
q.push(P(px,py));
}
}
}
while(t--)
{
int x,y; ll d;
cin>>x>>y>>d;
if(flag)
{
cout<<mp[x][y]<<'\n';
continue;
}
if(d<=dis[x][y]||(d-dis[x][y])%2==0)
cout<<mp[x][y]<<'\n';
else
cout<<1-(mp[x][y]-'0')<<'\n';
}
}
int main()
{
closeSync;
solve();
return 0;
}