LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并

传送门

题意:自己去看


首先可以知道,每一个点都有几率被选到,所以$i$与$V_i$的关系是确定了的。

所以我们只需要考虑每一个值的取到的概率。

很容易设计出一个$DP$:设$f_{i,j}$为在第$i$个点取到权值第$j$小的点的概率,转移就是$f_{i,j}=f_{lson,j} \times (\sum \limits _{k<i} f_{rson,k} \times p_x + \sum \limits _{k > i} f_{rson,k} \times (1 - p_x))$($lson$和$rson$之间可以交换),显然是可以前缀和优化的

当然前缀和优化也不够,$O(n^2)$只能过$40pts$。考虑优化。发现在合并的时候$lson$与$rson$之间的元素是互不冲突的,所以可以考虑线段树合并,每一次合并的时候把两边的贡献记录下来,在线段树上打标记即可。

  1 #include<bits/stdc++.h>
  2 #define ld long double
  3 #define int long long
  4 #define mid ((l + r) >> 1)
  5 #define lch Tree[now].ch[0]
  6 #define rch Tree[now].ch[1]
  7 //This code is written by Itst
  8 using namespace std;
  9 
 10 inline int read(){
 11     int a = 0;
 12     bool f = 0;
 13     char c = getchar();
 14     while(c != EOF && !isdigit(c)){
 15         if(c == '-')
 16             f = 1;
 17         c = getchar();
 18     }
 19     while(c != EOF && isdigit(c)){
 20         a = (a << 3) + (a << 1) + (c ^ '0');
 21         c = getchar();
 22     }
 23     return f ? -a : a;
 24 }
 25 
 26 const int MAXN = 300010 , MOD = 998244353;
 27 struct node{
 28     int mark , sum , ch[2];
 29 }Tree[MAXN * 20];
 30 int pri[MAXN] , root[MAXN] , lsh[MAXN] , ch[MAXN][2] , cnt , N , cntNode , ny;
 31 
 32 inline void pushup(int now){
 33     Tree[now].sum = (Tree[lch].sum + Tree[rch].sum) % MOD;
 34 }
 35 
 36 inline void pushdown(int now){
 37     if(Tree[now].mark != 1){
 38         Tree[lch].sum = Tree[lch].sum * Tree[now].mark % MOD;
 39         Tree[rch].sum = Tree[rch].sum * Tree[now].mark % MOD;
 40         Tree[lch].mark = Tree[lch].mark * Tree[now].mark % MOD;
 41         Tree[rch].mark = Tree[rch].mark * Tree[now].mark % MOD;
 42         Tree[now].mark = 1;
 43     }
 44 }
 45 
 46 void insert(int& now , int l , int r , int tar){
 47     if(!now){
 48         now = ++cntNode;
 49         Tree[now].mark = 1;
 50     }
 51     if(l == r){
 52         Tree[now].sum = 1;
 53         return;
 54     }
 55     pushdown(now);
 56     if(mid >= tar)
 57         insert(lch , l , mid , tar);
 58     else
 59         insert(rch , mid + 1 , r , tar);
 60     pushup(now);
 61 }
 62 
 63 int mer(int p , int q , int markp , int markq , int pri){
 64     if(!(p + q))
 65         return 0;
 66     if(!p){
 67         Tree[q].mark = Tree[q].mark * markq % MOD;
 68         Tree[q].sum = Tree[q].sum * markq % MOD;
 69         return q;
 70     }
 71     if(!q){
 72         Tree[p].mark = Tree[p].mark * markp % MOD;
 73         Tree[p].sum = Tree[p].sum * markp % MOD;
 74         return p;
 75     }
 76     pushdown(p);
 77     pushdown(q);
 78     int m1 = Tree[Tree[q].ch[1]].sum , n1 = Tree[Tree[p].ch[1]].sum , m2 = Tree[Tree[q].ch[0]].sum , n2 = Tree[Tree[p].ch[0]].sum;
 79     Tree[p].ch[0] = mer(Tree[p].ch[0] , Tree[q].ch[0] , (markp + m1 * (10000 - pri) % MOD * ny) % MOD , (markq + n1 * (10000 - pri) % MOD * ny) % MOD , pri);
 80     Tree[p].ch[1] = mer(Tree[p].ch[1] , Tree[q].ch[1] , (markp + m2 * pri % MOD * ny) % MOD , (markq + n2 * pri % MOD * ny) % MOD , pri);
 81     pushup(p);
 82     return p;
 83 }
 84 
 85 int getAns(int now , int l , int r){
 86     if(l == r)
 87         return l * lsh[l] % MOD * Tree[now].sum % MOD * Tree[now].sum % MOD;
 88     else{
 89         pushdown(now);
 90         return (getAns(lch , l , mid) + getAns(rch , mid + 1 , r)) % MOD;
 91     }
 92 }
 93 
 94 void dfs(int now){
 95     if(!ch[now][0])
 96         insert(root[now] , 1 , cnt , pri[now]);
 97     else
 98         if(!ch[now][1]){
 99             dfs(ch[now][0]);
100             root[now] = root[ch[now][0]];
101         }
102         else{
103             dfs(ch[now][0]);
104             dfs(ch[now][1]);
105             root[now] = mer(root[ch[now][0]] , root[ch[now][1]] , 0 , 0 , pri[now]);
106         }
107 }
108 
109 inline int poww(long long a , int b){
110     int times = 1;
111     while(b){
112         if(b & 1)
113             times = times * a % MOD;
114         a = a * a % MOD;
115         b >>= 1;
116     }
117     return times;
118 }
119 
120 signed main(){
121 #ifndef ONLINE_JUDGE
122     freopen("2537.in" , "r" , stdin);
123     //freopen("2537.out" , "w" , stdout);
124 #endif
125     N = read();
126     for(int i = 1 ; i <= N ; ++i){
127         int a = read();
128         if(!ch[a][0])
129             ch[a][0] = i;
130         else
131             ch[a][1] = i;
132     }
133     ny = poww(10000 , MOD - 2);
134     for(int i = 1 ; i <= N ; ++i){
135         pri[i] = read();
136         if(!ch[i][0])
137             lsh[++cnt] = pri[i];
138     }
139     sort(lsh + 1 , lsh + cnt + 1);
140     for(int i = 1 ; i <= N ; ++i)
141         if(!ch[i][0])
142             pri[i] = lower_bound(lsh + 1 , lsh + cnt + 1 , pri[i]) - lsh;
143     dfs(1);
144     cout << getAns(root[1] , 1 , cnt);
145     return 0;
146 }
posted @ 2018-11-30 21:10  cjoier_Itst  阅读(312)  评论(0编辑  收藏  举报