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;
}
posted @ 2026-10-22 07:27  elon_giao  阅读(4)  评论(0)    收藏  举报