「PKUWC2018」Minimax
作者:互联网
Solution
开始做完全没想到是线段树合并QAQ、
朴素的做法是直接树形dp。设\(f[u][x]\)表示在u点权值取到x的概率。
有转移:
如果x在左子树 \(f[u][x]=f[ls][x]\times \sum\limits_{y\in T_{rs},y<x}f[rs][y]\times p[u]+f[ls][x]\times \sum\limits_{y\in T_{rs},y>x}f[rs][y]\times (1-p[u])\)
就是以x作为最大值还是最小值出现来转移,x在右子树同理。
然鹅暴力做状态都存不下。考虑对每个节点开一棵权值线段树(主席树形式)这样空间复杂度\(\text O(nlogn)\)。
维护x的信息相当于合并x两儿子的线段树。
这时会发现枚举每个元素进行转移还是很假,考虑利用类似cdq分治的思想进行转移,分治前计算好右树对左树的贡献(对于左树每个点来说,右树贡献相同),和左树对右树的贡献,一直递归到叶节点,把贡献加进去就好了。
另外虽说主席树空间复杂度是\(\text O(nlogn)\),但是还是稍微开大一点,一般开N的40~50倍就差不多。
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
inline int read(){//be careful for long long!
register int x=0,f=1;register char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=0;ch=getchar();}
while(isdigit(ch)){x=x*10+(ch^'0');ch=getchar();}
return f?x:-x;
}
const int N=3e5+10,mod=998244353;;
int n,tr[N*50],ls[N*50],rs[N*50],cnt,p[N],rt[N],tag[N*50],w[N],maxn;
inline int power(int base,int n){int ans=1;for(;n;n>>=1,base=1ll*base*base%mod)if(n&1)ans=1ll*ans*base%mod;return ans;}
int tot,ans,inv=power(10000,mod-2);
vector<int> E[N];
inline void update(int p){tr[p]=(tr[ls[p]]+tr[rs[p]])%mod;}
inline void pushtag(int p,int v){tr[p]=1ll*tr[p]*v%mod,tag[p]=1ll*tag[p]*v%mod;}
inline void pushdown(int p){
if(tag[p]==1)return;
pushtag(ls[p],tag[p]),pushtag(rs[p],tag[p]);
tag[p]=1;
}
inline void insert(int &p,int l,int r,int pos){
if(!p)p=++cnt;tag[p]=tr[p]=1;
if(l==r)return;
int mid=(l+r)>>1;
if(pos<=mid)insert(ls[p],l,mid,pos);
else insert(rs[p],mid+1,r,pos);
update(p);
}
inline int merge(int x,int y,int px,int py,int p){
if(!(x+y))return 0;
if(!x){pushtag(y,py);return y;}
if(!y){pushtag(x,px);return x;}
int lx,rx,ly,ry;
pushdown(x),pushdown(y);
lx=(px+1ll*tr[rs[y]]*(1-p+mod)%mod)%mod;
ly=(py+1ll*tr[rs[x]]*(1-p+mod)%mod)%mod;
rx=(px+1ll*tr[ls[y]]*p%mod)%mod;
ry=(py+1ll*tr[ls[x]]*p%mod)%mod;
ls[x]=merge(ls[x],ls[y],lx,ly,p);
rs[x]=merge(rs[x],rs[y],rx,ry,p);
update(x);
return x;
}
inline void dfs(int nw){
for(int i=0;i<(int)E[nw].size();++i)
dfs(E[nw][i]);
if(!E[nw].size())insert(rt[nw],1,maxn,w[nw]);
else if(E[nw].size()==1)rt[nw]=rt[E[nw][0]];
else rt[nw]=merge(rt[E[nw][0]],rt[E[nw][1]],0,0,(int)(1ll*w[nw]*inv%mod));
}
inline void cal(int p,int l=1,int r=maxn){
if(!p)return;
if(l==r){
ans=(ans+1ll*tr[p]*tr[p]%mod*l%mod*(++tot)%mod)%mod;
return;
}
pushdown(p);
int mid=(l+r)>>1;
cal(ls[p],l,mid),cal(rs[p],mid+1,r);
}
int main(){
n=read();
for(int i=1;i<=n;++i)E[read()].push_back(i);
for(int i=1;i<=n;++i)maxn=max(maxn,w[i]=read());
dfs(1);cal(rt[1]);
printf("%d\n",ans);
return 0;
}
标签:ch,rs,int,Minimax,tr,tag,PKUWC2018,mod 来源: https://www.cnblogs.com/fruitea/p/12021208.html