Codeforces 68D - Half-decay Tree

题意

有一颗高度为 \(h\) 的完全二叉树(即点数为 \(2^{h+1}-1\) ),有两种操作:

  • add x y\(x\) 点的权值加 \(y\)
  • decay 一次衰变定义为选择一个叶子节点,断掉它到根的所有边,这样整个树会变成很多个连通块,一个连通块的权值是其中所有点的权值和;这个衰变的权值为这些连通块的权值中的最大值。这个操作要求输出随机选一个叶子进行衰变的期望权值。(衰变之间互不影响)

\(h\le 30,q\le 10^5\)

分析

一般这种完全二叉树都要利用其深度很小的性质。

可以发现,衰变的时候,最终得到的连通块都是由一个点和其一个子树构成的。对衰变求期望其实是求所有节点的衰变权值和。

对于一个点 \(x\) ,设其左儿子的子树权值和为 \(s_l\) ,右儿子的子树权值和为 \(s_r\) ,那么显然,若 \(s_l\ge s_r\) ,那么右子树中的所有点在衰变的时候,所取到的最大连通块都不可能使右子树中的。所以我们用当前的 \(\max\) 和左子树加当前点即可直接计算右子树的答案,接着递归进入左子树即可。

我们要维护的东西就是子树的权值和。

因此单次操作是 \(O(h\log n)\) 的(用 map )。

代码

#include<bits/stdc++.h>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/hash_policy.hpp>
using namespace std;
typedef __gnu_pbds::cc_hash_table<int,int> Map;
typedef long long giant;
inline char nchar() {
	static const int bufl=1<<20;
	static char buf[bufl],*a=NULL,*b=NULL;
	return a==b && (b=(a=buf)+fread(buf,1,bufl,stdin),a==b)?EOF:*a++;
}
template<class T> inline T read() {
	T x=0,f=1;
	char c=nchar();
	for (;!isdigit(c);c=nchar()) if (c=='-') f=-1;
	for (;isdigit(c);c=nchar()) x=x*10+c-'0';
	return x*f;
}
template<> char read<char>() {
	char c=nchar();
	for (;!isalpha(c);c=nchar());
	for (char f=nchar();isalpha(f);f=nchar());
	return c;
}
int h,q,last;
namespace tree {
	Map sum;
	void add(int x,int d) {
		for (;x;x>>=1) sum[x]+=d;
	}
	inline int size(int x) {
		return 1<<(h-(31-__builtin_clz(x)));
	}
	giant calc(int x,int mx) {
		if (x>=last) return max(mx,sum[x]);
		int lc=x<<1,rc=lc+1,sl=sum[lc],sr=sum[rc],sx=sum[x];
		giant ret=0;
		if (sl>sr) swap(lc,rc),swap(sl,sr);
		ret=(giant)size(lc)*max(sx-sl,mx);
		ret+=calc(rc,max(mx,sx-sr));
		return ret;
	}
	long double ans() {
		long double ret=calc(1,0);
		ret/=last;
		return ret;
	}
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("test.in","r",stdin);
#endif
	h=read<int>(),q=read<int>(),last=1<<h;
	while (q--) {
		char o=read<char>();
		if (o=='a') {
			int x=read<int>(),y=read<int>();
			tree::add(x,y);
		} else printf("%.12lf\n",(double)tree::ans());
	}
	return 0;
}
posted @ 2017-10-23 19:25  permui  阅读(534)  评论(0编辑  收藏  举报