CF 1535-Playoff Tournament
Posted Wise_XiaoWei4
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 1535-Playoff Tournament相关的知识,希望对你有一定的参考价值。
题意
给定深度为\\(k\\)的完全二叉树,每个节点有一个值\\(0/1/?\\),其中\\(0\\)代表选左值,\\(1\\)代表选右值,\\(?\\)代表二者都选。初始情况下,叶子结点下的节点值为\\(1\\)。
问每次修改一个节点后,根节点的值为多少。
解法
先根据初始状态建成一颗树,然后每次单点修改,时间复杂度\\(O(m * k)\\)。
小记
XX,完全自己想出来然后debug出来一道1800分的题目好有成就感(虽然好像原来就应该这样),不管了,睡觉睡觉。,开心。
Code
const int N = 1 << 21;
/*
构建一颗深度为k的完全二叉树,节点保存0/1/?,然后从根节点递归枚举当前可能的结果。
单点修改就可以,时间复杂度O(q * 18);
*/
int n;
char s[N];
char tr[N];
int nn ;
int cnt[N],ppp;
inline int ls(int u) {
return u << 1;
}
inline int rs(int u) {
return u << 1 | 1;
}
void modify(int pos,char x) {
int tmp = nn;
while(tmp) {
int now = (1 << (tmp - 1));
int num = now;
if(num < pos) pos -= num;
else {
ppp = now + pos - 1;
tr[now + pos - 1] = x;return ;
}
--tmp;
}
}
ll query(int u) {
if(u >= n) {
cnt[u] = 1;
return 1;
}
if(tr[u] == \'?\') {
cnt[u] = query(ls(u)) + query(rs(u));
return cnt[u];
}else if(tr[u] == \'1\') {
cnt[u] = query(rs(u));
query(ls(u));
return cnt[u];
}else if(tr[u] == \'0\') {
cnt[u] = query(ls(u));
query(rs(u));
return cnt[u];
}
}
void update() {
int tmp = ppp;
if(tr[ppp] == \'?\') {
cnt[ppp] = cnt[ls(ppp)] + cnt[rs(ppp)];
}else if(tr[ppp] == \'1\') {
cnt[ppp] = cnt[rs(ppp)];
}else if(tr[ppp] == \'0\') {
cnt[ppp] = cnt[ls(ppp)];
}
tmp >>= 1;
while(tmp) {
//cnt[tmp] = cnt[ls(tmp)] + cnt[rs(tmp)];
if(tr[tmp] == \'?\') cnt[tmp] = cnt[ls(tmp)] + cnt[rs(tmp)];
else if(tr[tmp] == \'1\') cnt[tmp] = cnt[rs(tmp)];
else if(tr[tmp] == \'0\') cnt[tmp] = cnt[ls(tmp)];
tmp >>= 1;
}
}
void solve() {
cin >> n >> (s + 1);
int tmp = n;
nn = n;
n = 1 << n;
int idx = 1;
while(tmp) {
int now = (1 << (tmp - 1));
int num = 1 << (tmp - 1);
while(num--) {
tr[now++] = s[idx++];
}
--tmp;
}
int m;cin >> m ;
query(1);
while(m--) {
int pos;char x;cin >> pos >> x;
modify(pos,x);
update();
cout << cnt[1] << endl;
}
}
以上是关于CF 1535-Playoff Tournament的主要内容,如果未能解决你的问题,请参考以下文章
[CF930E]/[CF944G]Coins Exhibition