[CF] 1535D Playoff Tournament 完全二叉树

题目链接
参考了这篇博客
思路:
1.把每场比赛当成二叉树的一个节点,决赛是根节点。
2.如果赛果是0/1 该节点可能的胜者数cnt来自底下对应的一个节点
3.如果赛果是? 该节点可能的胜者数cnt是它底下两节点之和

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <utility>
#include <map>
#include <vector>
#include <queue>
using namespace std;
typedef  long long LL;
const int N=3e5+10,M=6e5+10;
int cnt[M],n;
char s[N];
void update(int u)
{
	if(!u)return ;
	if(s[n-u]=='1')cnt[u]=cnt[u*2];//因为是倒着建的 所以高位的下标反而小
	else if(s[n-u]=='0')cnt[u]=cnt[u*2+1];
	else cnt[u]=cnt[u*2]+cnt[u*2+1];
	update(u/2);//往上更新赛果
}
void solve()
{
	int k;cin>>k;
	cin>>s+1;
	 n=1<<k;//8
	for(int i=2*n-1;i>=n;i--)cnt[i]=1;//开始时 总共2的k次方支队伍 初始化为1 接下来要用

	for(int i=n-1;i>=1;i--)update(i);//计算赛果

	int q;cin>>q;
	while(q--)
	{
		int x;char state;cin>>x>>state;
		s[x]=state;
		update(n-x);//x=1 n-x=7
		cout<<cnt[1]<<endl;//最终可能的胜者数
	}

}
int main()
{
cin.tie(0);ios::sync_with_stdio(false);
    int tests=1;
    while(tests--)
    {
    	solve();
    }
     return 0;
}
posted @ 2021-06-11 12:40  liv_vil  阅读(105)  评论(0)    收藏  举报