CF1535D Playoff Tournament
CF1535D Playoff Tournament
思路
很多人其实是被读入给恶心住了,那么我们就先将读入反转过来,然后把读入的每个 \(p\) 变为 \(|s|-p\)。按题意模拟即可,可以发现题目中的比赛好像一个线段树,我们可以把每场比赛的三种状态分别看成:
- 当 \(s_i=0\) 时,只取左儿子的权值
- 当 \(s_i=1\) 时,只取右儿子的权值
- 当 \(s_i =\ ?\) 时,取两个儿子的权值
在变化时只要单点修改,搜索到被修改的节点然后更新其权值。
ACcode:
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define endl '\n'
#define inf 0x7f7f7f7f7f7f7f7f
const int N=(1<<19)+1;
int k,n,q,i,fl[N],sum[N],lo;
string s;
void pushup(int id){
int l=id<<1,r=id<<1|1;
sum[id]=0;
if(fl[id]==0||fl[id]==2) sum[id]+=sum[l];
if(fl[id]==0||fl[id]==1) sum[id]+=sum[r];
}
void build(int id,int l,int r){
if(l==r){
sum[id]=1;
return ;
}
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
pushup(id);
}
void cg(int x,int id,int l,int r,int op,int dep){
if(id==x){
fl[id]=op;
pushup(id);
return ;
}
int mid=(l+r)>>1;
if(x>>(lo-dep-2)&1) cg(x,id<<1|1,mid+1,r,op,dep+1);
else cg(x,id<<1,l,mid,op,dep+1);
pushup(id);
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
freopen("tournament.in","r",stdin);
freopen("tournament.out","w",stdout);
//↑以上为初始化 ↑
//------------------------------
cin >> k >> s;
n=(1<<k);
for(i = s.size()-1;i>=0;--i)
fl[n-i-1]=(s[i]=='?'?0:(s[i]=='0'?1:2));
build(1,1,n);
cin >> q;
for(i = 1;i<=q;++i){
int x;char c;
cin >> x >> c;
x=n-x;
lo=ceil(log2(x));
// for(int i = 1;i<n;++i) cout << fl[i] << ' ';
// cout << endl;
cg(x,1,1,n,(c=='?'?0:(c=='0'?1:2)),0);
cout << sum[1] << endl;
}
// for(int i = 1;i<n;++i) cout << fl[i] << ' ';
return 0;
}

浙公网安备 33010602011771号