【pkuwc2018】 【loj2537】 Minmax DP+线段树合并

今年年初的时候参加了PKUWC,结果当时这一题想了快$2h$都没有想出来....

哇我太菜啦....

 

昨天突然去搜了下哪里有题,发现$loj$上有于是就去做了下。

结果第一题我5分钟就把所有细节都想好了啊5555....

场上$60pts$消失...


 

 

显然,我们可以用$f[i][j]$表示节点$i$值为第$j$大的值的概率。

我们不难列出$dp$式子,$f[i][j]=f[s1][j] \times (s[s2][j-1]\times p+(s[s2][m]-s[s2][j])\times (1-p))$。

其中$s[i][j]=\sum_{k=0}^{j} f[i][k]$。$s1$表示可以取到第j大的数的儿子,$s2$表示不能取到第$j$大的数的儿子。

显然,直接转移是$O(n^2)$的(我场上就写了这个)。

 

考虑如何进行优化。

题目中有一些特别优美的条件,比如说所有的数不会重复,树最多只有两个分叉。

如果某个树只有一个分叉的话,显然直接复制根即可,时间复杂度为$O(1)$。

考虑用线段树优化,考虑如何合并$s1$和$s2$这两棵树。

假设我们当前要合并的区间为$[l,r]$,且$x,y$分别为线段树中$s1,s2$用来表示区间$[l,r]$的节点。

对于该区间,我们用$xs1$来表示$s[s2][l-1]$,用$xs2$来表示$(s[s2][m]-s[s2][r])$。对于$s2$同理(暂且用$ys1,ys2$表示)。

递归的时候,若往线段树的左儿子递归,那么$xs2$就要加上$x$的右儿子的概率和,$ys2$同理。若线段树往右儿子递归,也同理。

然后当递归到$x$或$y$中有一个不存在时,考虑回这个dp式子:

$f[i][j]=f[s1][j] \times (s[s2][j-1]\times p+(s[s2][m]-s[s2][j])\times (1-p))$

不妨设x存在但y不存在,在这连续的一段中,我们发现这些f需要乘上的数(指$(s[s2][j-1]\times p+(s[s2][m]-s[s2][j])\times (1-p))$这一段),他们都是一样的,所以直接打一个区间乘的标记就可以了

(若$l==r$,则更新方式与上述$dp$式子相同,若$l≠r$,打个标记就行了)

考虑到线段树合并的时间复杂度为$O(n log n)$。所以这种方法是可以通过的。

 

完结撒花~~

  1 #include<bits/stdc++.h>
  2 #define L long long
  3 #define MOD 998244353
  4 #define M 300005
  5 using namespace std;
  6 
  7 L pow_mod(L x,L k){
  8     L ans=1;
  9     while(k){
 10         if(k&1) ans=ans*x%MOD;
 11         x=x*x%MOD; k>>=1;
 12     }
 13     return ans;
 14 }
 15 
 16 int lc[M*20]={0},rc[M*20]={0},root[M]={0},use=0;
 17 L p[M*20]={0},tag[M*20]={0},gailv[M]={0};
 18 int l[M]={0},r[M]={0};
 19 
 20 void pushdown(int x){
 21     if(tag[x]!=1){
 22         if(lc[x]!=0) tag[lc[x]]=tag[lc[x]]*tag[x]%MOD,p[lc[x]]=p[lc[x]]*tag[x]%MOD;
 23         if(rc[x]!=0) tag[rc[x]]=tag[rc[x]]*tag[x]%MOD,p[rc[x]]=p[rc[x]]*tag[x]%MOD;
 24         tag[x]=1;
 25     }
 26 }
 27 void pushup(int x){p[x]=(p[lc[x]]+p[rc[x]])%MOD;}
 28 
 29 void updata(int &x,int l,int r,int k){
 30     if(!x) {x=++use; p[x]=tag[x]=1;}
 31     if(l==r){p[x]=tag[x]=1; return;} 
 32     int mid=(l+r)>>1;
 33     if(k<=mid) updata(lc[x],l,mid,k);
 34     if(mid<k) updata(rc[x],mid+1,r,k);
 35     pushup(x);
 36 }
 37 
 38 L nowp;
 39 int solve(int x,int y,L xs1,L xs2,L ys1,L ys2){
 40     if(x==0&&y==0) return 0;
 41     if(y==0){
 42         L upd=(xs1*nowp+xs2*(1-nowp+MOD))%MOD;
 43         tag[x]=upd*tag[x]%MOD;
 44         p[x]=upd*p[x]%MOD;
 45         return x;
 46     }
 47     if(x==0){
 48         L upd=(ys1*nowp+ys2*(1-nowp+MOD))%MOD;
 49         tag[y]=upd*tag[y]%MOD;
 50         p[y]=upd*p[y]%MOD;
 51         return y;
 52     }
 53     pushdown(x); pushdown(y);
 54     L p1=p[lc[y]],p2=p[lc[x]];
 55     lc[x]=solve(lc[x],lc[y],xs1,(xs2+p[rc[y]])%MOD,ys1,(ys2+p[rc[x]])%MOD);
 56     rc[x]=solve(rc[x],rc[y],(xs1+p1)%MOD,xs2,(ys1+p2)%MOD,ys2);
 57     pushup(x);
 58     return x;
 59 }
 60 
 61 void dfs(int x){
 62     if(l[x]) dfs(l[x]);
 63     if(r[x]) dfs(r[x]);
 64     if(!l[x]) return;
 65     if(!r[x]) {root[x]=root[l[x]]; return;}
 66     nowp=gailv[x];
 67     root[x]=solve(root[l[x]],root[r[x]],0,0,0,0);
 68 }
 69 L w[M]={0},hh[M]={0}; int m=0;
 70 
 71 L ans=0;
 72 void getans(int x,L l,L r){
 73     if(l==r){
 74         ans=(ans+l*hh[l]%MOD*p[x]%MOD*p[x])%MOD;
 75         return;
 76     }
 77     pushdown(x);
 78     L mid=(l+r)>>1;
 79     getans(lc[x],l,mid);
 80     getans(rc[x],mid+1,r);
 81 }
 82 
 83 int main(){
 84     //freopen("in.txt","r",stdin);
 85     //freopen("out.txt","w",stdout);
 86     int n; scanf("%d",&n);
 87     for(int i=1;i<=n;i++){
 88         int x; scanf("%d",&x);
 89         if(!l[x]) l[x]=i;
 90         else r[x]=i;
 91     }
 92     L inv10000=pow_mod(10000,MOD-2);
 93     for(int i=1;i<=n;i++){
 94         L x; scanf("%lld",&x);
 95         if(l[i]) gailv[i]=x*inv10000%MOD;
 96         else w[i]=x,hh[++m]=x;
 97     }
 98     sort(hh+1,hh+m+1);
 99     for(int i=1;i<=n;i++) if(w[i]){
100         int x; x=lower_bound(hh+1,hh+m+1,w[i])-hh;
101         updata(root[i],1,m,x);
102     }
103     dfs(1);
104     getans(root[1],1,m);
105     printf("%lld\n",ans);
106 }

 

 

posted @ 2018-05-31 11:09  AlphaInf  阅读(314)  评论(4编辑  收藏  举报