LOJ2537:[PKUWC2018]Minimax——题解
参考了本题在网上能找到的为数不多的题解。
以及我眼睛瞎没看到需要离散化,还有不开longlong见祖宗。
————————————————————————————
思考一下不难发现,我们的操作相当于对两个数集进行合并,并且重新更新每个数被取到的期望。
权值线段树可以帮我们实现这个功能(当然是要动态开点了)。
然后就思考线段树的合并操作了,orz可我不会啊。
设我们期望让左儿子的数字u成为其父亲的权值,其父亲选最大值的概率为k,u在右儿子数集中比它小的数被选中的期望设为w。
则概率为pu*((1-w)*(1-k)+w*k)=pu*(1-w-k+2*w*k)。
当然右儿子同理。
当然统计w显然不能暴力统计,我们权值线段树维护当前区间所有数被选中的期望和,从左到右扫所有可能的最大区间,这个区间满足有一个儿子的数集并不包含这个区间内的任意一个数。
这样这个区间的期望和就能被缩成了“一个数的期望”,此时的w也很容易被统计出来(就相当于这个区间以前的所有数的期望和,每次扫完一个区间累加即可O(1)求出),那么这个时候就被转换成了区间修改问题。
#include<cmath> #include<queue> #include<cstdio> #include<cctype> #include<cstring> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int N=3e5+5; const int p=998244353; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } int qpow(int k,int n){ int res=1; while(n){ if(n&1)res=(ll)res*k%p; k=(ll)k*k%p;n>>=1; } return res; } struct tree{ int l,r; ll p,lazy; }tr[N*20]; int fa[N],son[N],ch[N][2],rt[N],pool,n,m,b[N],q[N]; inline void LSH(){ sort(b+1,b+m+1); m=unique(b+1,b+m+1)-b-1; for(int i=1;i<=n;i++) if(!son[i]) q[i]=lower_bound(b+1,b+m+1,q[i])-b; } void insert(int &x,int l,int r,int k){ tr[x=++pool].p=1;tr[x].lazy=1; if(l==r)return; int mid=(l+r)>>1; if(k<=mid)insert(tr[x].l,l,mid,k); else insert(tr[x].r,mid+1,r,k); } inline void push(int x){ if(tr[x].lazy<=1)return; (tr[tr[x].l].lazy*=tr[x].lazy)%=p; (tr[tr[x].r].lazy*=tr[x].lazy)%=p; (tr[tr[x].l].p*=tr[x].lazy)%=p; (tr[tr[x].r].p*=tr[x].lazy)%=p; tr[x].lazy=1; } int maxl,maxr; int merge(int nl,int nr,int l,int r,int k){ if(!nl&&!nr)return 0; if(!nl){ (maxr+=tr[nr].p)%=p; (tr[nr].p*=((ll)2*maxl%p*k%p-k-maxl+1)%p+p)%=p; (tr[nr].lazy*=((ll)2*maxl%p*k%p-k-maxl+1)%p+p)%=p; return nr; } if(!nr){ (maxl+=tr[nl].p)%=p; (tr[nl].p*=((ll)2*maxr%p*k%p-k-maxr+1)%p+p)%=p; (tr[nl].lazy*=((ll)2*maxr%p*k%p-k-maxr+1)%p+p)%=p; return nl; } push(nl);push(nr); int mid=(l+r)>>1; tr[nl].l=merge(tr[nl].l,tr[nr].l,l,mid,k); tr[nl].r=merge(tr[nl].r,tr[nr].r,mid+1,r,k); tr[nl].p=(tr[tr[nl].l].p+tr[tr[nl].r].p)%p; return nl; } void dfs(int u){ if(!son[u]){ insert(rt[u],1,m,q[u]);return; } if(son[u]==1){ dfs(ch[u][0]); rt[u]=rt[ch[u][0]]; }else{ dfs(ch[u][0]);dfs(ch[u][1]); maxl=maxr=0; rt[u]=merge(rt[ch[u][0]],rt[ch[u][1]],1,m,q[u]); } } int cnt; int query(int x,int l,int r){ if(!tr[x].p)return 0; if(l==r){ cnt++; return (ll)cnt*b[l]%p*tr[x].p%p*tr[x].p%p; } push(x); int mid=(l+r)>>1; return (query(tr[x].l,l,mid)+query(tr[x].r,mid+1,r))%p; } int main(){ n=read(); for(int i=1;i<=n;i++){ fa[i]=read(); ch[fa[i]][son[fa[i]]++]=i; } int inv=qpow(10000,p-2); for(int i=1;i<=n;i++){ q[i]=read(); if(son[i])q[i]=(ll)q[i]*inv%p; else b[++m]=q[i]; } LSH(); dfs(1); printf("%d\n",query(rt[1],1,m)); return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+
+++++++++++++++++++++++++++++++++++++++++++