zoukankan      html  css  js  c++  java
  • LOJ2537 PKUWC2018 Minimax 树形DP、线段树合并

    传送门

    题意:自己去看


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

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

    很容易设计出一个$DP$:设$f_{i,j}$为在第$i$个点取到权值第$j$小的点的概率,转移就是$f_{i,j}=f_{lson,j} imes (sum limits _{k<i} f_{rson,k} imes p_x + sum limits _{k > i} f_{rson,k} imes (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 }
  • 相关阅读:
    List数组细解
    iOS之缓存
    Java_String的操作
    weak的理解
    Swift_单利
    Java 抽象类和接口
    Java 继承中的问题
    java 成员变量与局部变量
    纪中第十九天
    cin快读
  • 原文地址:https://www.cnblogs.com/Itst/p/10046531.html
Copyright © 2011-2022 走看看