zoukankan      html  css  js  c++  java
  • 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<dep_x\),并且只会从\(LCA(x,z)\)处向上开始产生影响。

    发现一个特点是从\(LCA\)处产生影响,这就和[LNOI2014]LCA很像了,我们对于会产生影响的\(z\)把它到根节点上的路径都修改了,然后直接询问\(x\)到根节点路径上的权值就好了。

    至于\(dep_z<dep_x\)这个条件我们把所有节点按照深度从小到大排序然后处理即可。

    时间复杂度:\(O(n\log^2 n)\)


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #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]<dep[y];}
    signed main()
    {
    	inv100=power(100,P-2);
    	scanf("%lld",&n);
    	for(ll i=1;i<=n;i++){
    		scanf("%lld",&c[i]);p[i]=i;
    		c[i]=(100-c[i])*inv100%P;
    	}
    	for(ll i=1;i<n;i++){
    		ll x,y;
    		scanf("%lld%lld",&x,&y);
    		addl(x,y);addl(y,x);
    	}
    	dfs1(1);top[1]=1;dfs2(1);
    	sort(p+1,p+1+n,cmp);
    	T.Build(1,1,n);
    	for(ll i=2,l=1;i<=n+1;i++){
    		if(dep[p[i]]!=dep[p[i-1]]){
    			ll r=i-1;
    			for(ll j=l;j<=r;j++)
    				ans[p[j]]=Ask(p[j]);
    			for(ll j=l;j<=r;j++)
    				Updata(p[j],c[p[j]]);
    			l=i;
    		}
    	}
    	for(ll i=1;i<=n;i++)
    		printf("%lld\n",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    JAVA-初步认识-常用对象API(集合框架-重点方法keyset演示图解)
    JAVA-初步认识-常用对象API(集合框架-常用方法演示)
    JAVA-初步认识-常用对象API(集合框架-Map集合特点常用方法)
    JAVA-初步认识-常用对象API(集合框架-练习-字符串长度排序)
    JAVA-初步认识-常用对象API(集合框架-treeset集合-二叉树)
    JAVA-初步认识-常用对象API(集合框架-treeset集合-Comparator比较器)9
    JAVA-初步认识-常用对象API(集合框架-treeset集合)
    JAVA-初步认识-常用对象API(集合框架-LinkedHashset集合)
    Spring整合hibernate的一个例子:用事务买书
    Spring整合hibernate的一个例子:用事务买书
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/15735475.html
Copyright © 2011-2022 走看看