luogu P5298 [PKUWC2018]Minimax
题面传送门
我们先来考虑一个很sb的\(O(n^2)\)的dp
设\(dp_{i,j}\)为\(i\)这个节点为\(j\)权值的概率,那么显然的可以枚举两个儿子的权值然后暴力转移。
因为这个时间复杂度弱于每个叶子向上暴力跳的复杂度,还可以过随机的\(10\)分。
然后发现这个东西是和前后缀和有关所以可以写个线段树合并维护,时间复杂度\(O(nlogn)\)
code:
#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 300000
#define K 1000000
#define mod 998244353
#define Mod (mod-1)
#define eps (1e-5)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*x+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
int n,m,k,x,In[N+5],Ns[N+5],Nh,Ro[N+5],cnt;ll P[N+5],ToT;
struct yyy{int to,z;};struct ljb{int head,h[N+5];yyy f[N+5<<1];I void add(int x,int y){f[++head]=(yyy){y,h[x]};h[x]=head;}}s;
I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}const ll Inv=mpow(10000);
namespace Tree{
#define ls L[now]
#define rs R[now]
int L[N*30+5],R[N*30+5];ll F[N*30+5],Fl[N*30+5];I void Up(int now){F[now]=(F[ls]+F[rs])%mod;}
I void PF(int now,ll w){now&&(Fl[now]=Fl[now]*w%mod,F[now]=F[now]*w%mod);}I void P(int now){Fl[now]^1&&(PF(ls,Fl[now]),PF(rs,Fl[now]),Fl[now]=1);}
I void Ins(int x,int &now,int l=1,int r=Nh){!now&&(now=++cnt,Fl[cnt]=1);F[now]=1;if(l==r) return;int m=l+r>>1;x<=m?Ins(x,ls,l,m):Ins(x,rs,m+1,r);}
I int Merge(int x,int y,ll Ls1,ll Ls2,ll Rs1,ll Rs2,ll Ps){
printf("%d %d %lld %lld %lld %lld %lld\n",x,y,Ls1,Ls2,Rs1,Rs2,Ps);if(!x||!y){if(x) PF(x,(Ls2*Ps+Rs2*(1+mod-Ps))%mod);if(y) PF(y,(Ls1*Ps+Rs1*(1+mod-Ps))%mod);return x|y;}
P(x);P(y);ll Lx=F[L[x]],Ly=F[L[y]],Rx=F[R[x]],Ry=F[R[y]];L[x]=Merge(L[x],L[y],Ls1,Ls2,(Rs1+Rx)%mod,(Rs2+Ry)%mod,Ps);R[x]=Merge(R[x],R[y],(Ls1+Lx)%mod,(Ls2+Ly)%mod,Rs1,Rs2,Ps);return Up(x),x;
}
I void GA(int &now,int l=1,int r=Nh){if(l==r) {ToT+=1ll*l*Ns[l]%mod*F[now]%mod*F[now]%mod;printf("%lld\n",F[now]);return;}int m=l+r>>1;P(now);GA(ls,l,m);GA(rs,m+1,r);}
}
I void dfs(int x){
RI i,L[2],H=0;if(!In[x]) return Tree::Ins(P[x],Ro[x]);
yyy tmp;for(RI i=s.h[x];i;i=tmp.z){
tmp=s.f[i];dfs(tmp.to);if(In[x]==1) {Ro[x]=Ro[tmp.to];return;}L[H++]=tmp.to;
}Ro[x]=Tree::Merge(Ro[L[0]],Ro[L[1]],0,0,0,0,P[x]);
}
int main(){
freopen("1.in","r",stdin);
RI i;scanf("%d",&n); for(i=1;i<=n;i++)scanf("%d",&x),x&&(s.add(x,i),In[x]++);for(i=1;i<=n;i++) scanf("%lld",&P[i]),In[i]?(P[i]=P[i]*Inv%mod):(Ns[++Nh]=P[i]);
sort(Ns+1,Ns+Nh+1);Nh=unique(Ns+1,Ns+Nh+1)-Ns-1;for(i=1;i<=n;i++) !In[i]&&(P[i]=lower_bound(Ns+1,Ns+Nh+1,P[i])-Ns);dfs(1);Tree::GA(Ro[1]);printf("%lld\n",ToT%mod);
}