专栏文章

题解:CF1866I Imagination Castle

CF1866I题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@minvdk82
此快照首次捕获于
2025/12/02 08:58
3 个月前
此快照最后确认于
2025/12/02 08:58
3 个月前
查看原文

做法

首先考虑暴力 DP,设 dpi,jdp_{i,j} 代表先手走完之后到了 (i,j)(i,j) 时是先手必胜还是必败(11 表示必胜, 00 表示必败)。显然有对于所有关键点,dpXi,Yi=1dp_{X_i,Y_i}=1,且 dpn,m=1dp_{n,m}=1。倒着 DP 即可。
考虑优化。发现 dpi,j=1dp_{i,j}=1 当且仅当 (i,j)(i,j) 无法走到任何 dpx,y=1dp_{x,y}=1 的位置(否则下一轮轮到后手就可以直接走到一个必胜点)。于是可以发现一个重要性质:不考虑关键点,每行和每列最多有一个 11。于是考虑设 fif_i 表示第 ii 行除了关键点的 11 在哪个位置,gig_i 表示第 ii 列除了关键点的 11 在哪个位置(1-1 表示没有)。发现只要知道了所有大于 iijjfjf_j,就能算出 fif_i。于是 ffgg 是独立的,分别倒着计算即可。
具体地,fif_i 需要不能走到它下面的 11,设 tt 为所有大于 ii 的行的 11 所在的列的 MEX。如果 tt 大于这一行所有关键点所在列的最大值,那么 fi=tf_i=t,否则 fi=1f_i=-1。用 set 维护即可。

代码

CPP
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define ull unsigned long long
#define pii pair<ll,ll>
#define fi first
#define se second
#define i128 __int128
#define ALL(x) x.begin(),x.end()
#define popcount(x) __builtin_popcountll(x)
#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 42
#endif
using namespace std;
const int INF=1e18;
const int N=200005;
const int MOD1=1e9+7,MOD2=998244353;
const int MOD=MOD1;
int n,m,k;
int f[N],g[N];//这一行/列除了关键点的1 
vector<int> vec1[N],vec2[N];
set<int> s;
void calc(int x){
    //计算行
    int t=(!s.empty()?*s.rbegin():-1);
    int mx=0;
    for(auto i:vec1[x]){
        mx=max(mx,i);
    }
    //debug(x,mx,t);
    if(t>mx)f[x]=t;
    for(auto i:vec1[x]){
        s.erase(i);
    }
    if(f[x]!=-1){
        s.erase(f[x]);
    }
    if(x!=1)calc(x-1);
}
void calc2(int x){
    int t=(!s.empty()?*s.rbegin():-1);
    int mx=0;
    for(auto i:vec2[x]){
        mx=max(mx,i);
    }
    if(t>mx)g[x]=t;
    for(auto i:vec2[x]){
        s.erase(i);
    }
    if(g[x]!=-1){
        s.erase(g[x]);
    }
    if(x!=1)calc2(x-1);
}
void solve_(){
    cin>>n>>m>>k;
    bool flg=0;
    bool flg2=0;
    for(int i=1;i<=k;i++){
        int x,y;
        cin>>x>>y;
        if(x==1||y==1){
            flg=1;
        }
        if(x==n&&y==m){
            flg2=1;
        }
        vec1[x].push_back(y);
        vec2[y].push_back(x);
    }
    if(!flg2){
        vec1[n].push_back(m);
        vec2[m].push_back(n);
    }
    if(n==1&&m==1){
        cout<<"Bhinneka\n";
        return;
    }
    if(n==1||m==1){
        cout<<"Chaneka\n";
        return;
    }
    if(flg==1){
        cout<<"Chaneka\n";
        return;
    }
    for(int i=1;i<=n;i++){
        f[i]=-1;
    }
    for(int i=1;i<=m;i++){
        g[i]=-1;
    }
    for(int i=1;i<=m;i++){
        s.insert(i);
    }
    calc(n);
    s.clear();
    for(int i=1;i<=n;i++){
        s.insert(i);
    }
    calc2(m);
    for(int i=2;i<=n;i++){
        if(f[i]==1){
            cout<<"Chaneka\n";
            return;
        }
    }
    for(int i=2;i<=m;i++){
        if(g[i]==1){
            cout<<"Chaneka\n";
            return;
        }
    }
    cout<<"Bhinneka\n";
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int testcase,multitest=0;
    if(multitest)cin>>testcase;
    else testcase=1;
    while(testcase--){
        solve_();
    }
    return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...