51nod-动物与游戏【树链剖分,线段树】
正题
题目链接:http://www.51nod.com/Contest/Problem.html#contestProblemId=3957
题目大意
\(n\)个点的一棵树,第\(i\)个节点上的动物有\(\frac{a_i}{100}\)的概率加入,每个加入的动物都会每秒向父节点移动。
对于第\(i\)只动物,如果它到达一个节点时还没有其他动物比他早来过,那么它的权值加一。
现在对于每一只动物求它参加的话它的期望权值。
\(1\leq n\leq 10^5,1\leq a_i\leq 100\)
解题思路
考虑一个动物\(x\)能拿到一个节点\(y\)的权值的条件,也就是\(y\)的子树中深度比\(x\)小的动物都不参赛的概率。
也就是对于一个动物\(x\),动物\(z\)能对它产生影响首先要求\(dep_z
发现一个特点是从\(LCA\)处产生影响,这就和[LNOI2014]LCA很像了,我们对于会产生影响的\(z\)把它到根节点上的路径都修改了,然后直接询问\(x\)到根节点路径上的权值就好了。
至于\(dep_z
时间复杂度:\(O(n\log^2 n)\)
code
#include
#include
#include
#define ll long long
using namespace std;
const ll N=1e5+10,P=998244353;
struct node{
ll to,next;
}a[N<<1];
ll n,tot,cnt,inv100,fa[N],ls[N],c[N],p[N],ans[N];
ll siz[N],dep[N],son[N],top[N],seq[N],id[N];
ll power(ll x,ll b){
ll ans=1;
while(b){
if(b&1)ans=ans*x%P;
x=x*x%P;b>>=1;
}
return ans;
}
void addl(ll x,ll y){
a[++tot].to=y;
a[tot].next=ls[x];
ls[x]=tot;return;
}
struct Seq_Tree{
ll w[N<<2],lazy[N<<2];
void Downdata(ll x){
if(lazy[x]==1)return;
w[x*2]=w[x*2]*lazy[x]%P;
w[x*2+1]=w[x*2+1]*lazy[x]%P;
lazy[x*2]=lazy[x*2]*lazy[x]%P;
lazy[x*2+1]=lazy[x*2+1]*lazy[x]%P;
lazy[x]=1;return;
}
void Build(ll x,ll L,ll R){
lazy[x]=1;
if(L==R){w[x]=1;return;}
ll mid=(L+R)>>1;
Build(x*2,L,mid);
Build(x*2+1,mid+1,R);
w[x]=w[x*2]+w[x*2+1];
}
void Change(ll x,ll L,ll R,ll l,ll r,ll val){
if(L==l&&R==r){w[x]=w[x]*val%P;lazy[x]=lazy[x]*val%P;return;}
ll mid=(L+R)>>1;Downdata(x);
if(r<=mid)Change(x*2,L,mid,l,r,val);
else if(l>mid)Change(x*2+1,mid+1,R,l,r,val);
else Change(x*2,L,mid,l,mid,val),Change(x*2+1,mid+1,R,mid+1,r,val);
w[x]=(w[x*2]+w[x*2+1])%P;
}
ll Ask(ll x,ll L,ll R,ll l,ll r){
if(L==l&&R==r)return w[x];
ll mid=(L+R)>>1;Downdata(x);
if(r<=mid)return Ask(x*2,L,mid,l,r);
if(l>mid)return Ask(x*2+1,mid+1,R,l,r);
return (Ask(x*2,L,mid,l,mid)+Ask(x*2+1,mid+1,R,mid+1,r))%P;
}
}T;
void dfs1(ll x){
siz[x]=1;dep[x]=dep[fa[x]]+1;
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==fa[x])continue;
fa[y]=x;dfs1(y);
siz[x]+=siz[y];
if(siz[y]>siz[son[x]])son[x]=y;
}
return;
}
void dfs2(ll x){
id[x]=++cnt;seq[cnt]=x;
if(son[x]){
top[son[x]]=top[x];
dfs2(son[x]);
}
for(ll i=ls[x];i;i=a[i].next){
ll y=a[i].to;
if(y==son[x]||y==fa[x]) continue;
top[y]=y;dfs2(y);
}
}
void Updata(ll x,ll val){
while(x){
T.Change(1,1,n,id[top[x]],id[x],val);
x=fa[top[x]];
}
return;
}
ll Ask(ll x){
ll ans=0;
while(x){
(ans+=T.Ask(1,1,n,id[top[x]],id[x]))%=P;
x=fa[top[x]];
}
return ans;
}
bool cmp(ll x,ll y)
{return dep[x]