Codeforces 1349C/1350E - Orac and Game of Life (bfs)

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;
}

posted @ 2020-09-21 20:29  StelaYuri  阅读(201)  评论(0编辑  收藏  举报