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

浙公网安备 33010602011771号