zoukankan      html  css  js  c++  java
  • BZOJ5210 最大连通子块和 【树链剖分】【堆】【动态DP】

    题目分析:

    解决了上次提到的《切树游戏》后,这道题就是一道模板题。

    注意我们需要用堆维护子重链的最大值。这样不会使得复杂度变坏,因为每个重链我们只考虑一个点。

    时间复杂度$O(nlog^2n)$

    代码:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 
      4 typedef long long ll;
      5 
      6 const int maxn = 202000;
      7 
      8 int n,m;
      9 int v[maxn];
     10 vector<int> g[maxn];
     11 int fa[maxn],dep[maxn],sz[maxn],son[maxn],top[maxn],tail[maxn];
     12 int where[maxn],number[maxn],num;
     13 ll TOT[maxn];
     14 
     15 struct Priority_queue{
     16     priority_queue <ll,vector<ll>,less<ll> > pq,del;
     17     void Insert(ll now){pq.push(now);}
     18     void Erase(ll now){del.push(now);}
     19     ll Top(){
     20     while(!del.empty()&&pq.top() == del.top()) pq.pop(),del.pop();
     21     return pq.top();
     22     }
     23     int Size(){return pq.size()-del.size();}
     24 }PQ[maxn];
     25 
     26 struct node{ll L,R,D,C;}T[maxn<<2];
     27 
     28 void push_up(int now){
     29     T[now].L = max(T[now<<1].L,T[now<<1].C+T[now<<1|1].L);
     30     T[now].R = max(T[now<<1|1].R,T[now<<1|1].C+T[now<<1].R);
     31     T[now].D = max(max(T[now<<1].D,T[now<<1|1].D),T[now<<1].R+T[now<<1|1].L);
     32     T[now].C = T[now<<1].C+T[now<<1|1].C; 
     33 }
     34 
     35 node merge(node alpha,node beta){
     36     node gamma; gamma.L = max(alpha.L,alpha.C+beta.L);
     37     gamma.R = max(beta.R,beta.C+alpha.R);
     38     gamma.D = max(max(alpha.D,beta.D),alpha.R+beta.L);
     39     gamma.C = alpha.C+beta.C;
     40     return gamma;
     41 }
     42 
     43 char readchar(){
     44     char ch = getchar(); while(ch != 'M' && ch != 'Q') ch = getchar();
     45     return ch;
     46 }
     47 
     48 void read(){
     49     scanf("%d%d",&n,&m);
     50     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
     51     for(int i=1;i<n;i++){
     52     int x,y; scanf("%d%d",&x,&y);
     53     g[x].push_back(y); g[y].push_back(x);
     54     }
     55 }
     56 
     57 void dfs1(int now,int f,int dp){
     58     fa[now] = f; dep[now] = dp;
     59     for(int i=0;i<g[now].size();i++){
     60     if(g[now][i] == f) continue;
     61     dfs1(g[now][i],now,dp+1);
     62     sz[now] += sz[g[now][i]];
     63     if(son[now]==0||sz[son[now]]<sz[g[now][i]])son[now]=g[now][i];
     64     }
     65     sz[now]++;
     66     if(son[now]) tail[now] = tail[son[now]];
     67     else tail[now] = now;
     68 }
     69 
     70 void dfs2(int now,int tp){
     71     top[now] = tp;number[now] = ++num; where[num] = now;
     72     if(son[now]) dfs2(son[now],tp);
     73     for(int i=0;i<g[now].size();i++){
     74     if(g[now][i] == fa[now] || g[now][i] == son[now]) continue;
     75     dfs2(g[now][i],g[now][i]);
     76     }
     77 }
     78 
     79 void Modify(int now,int tl,int tr,int place){
     80     if(tl == tr){
     81     tl = where[tl];
     82     T[now].C = TOT[tl] + v[tl];
     83     T[now].L = max(0ll,TOT[tl]+v[tl]); T[now].R = T[now].L;
     84     if(PQ[tl].Size()) T[now].D = max(PQ[tl].Top(),T[now].L);
     85     else T[now].D = T[now].L;
     86     }else{
     87     int mid = (tl+tr)/2;
     88     if(place <= mid) Modify(now<<1,tl,mid,place);
     89     else Modify(now<<1|1,mid+1,tr,place);
     90     push_up(now);
     91     }
     92 }
     93 
     94 node Query(int now,int tl,int tr,int l,int r){
     95     if(tl >= l && tr <= r) return T[now];
     96     int mid = (tl+tr)/2;
     97     if(r <= mid) return Query(now<<1,tl,mid,l,r);
     98     if(l > mid) return Query(now<<1|1,mid+1,tr,l,r);
     99     return merge(Query(now<<1,tl,mid,l,r),Query(now<<1|1,mid+1,tr,l,r));
    100 }
    101 
    102 void dfs3(int now){
    103     if(son[now]) dfs3(son[now]);
    104     for(int i=0;i<g[now].size();i++){
    105     int mp = g[now][i];
    106     if(mp == fa[now] || mp == son[now]) continue;
    107     dfs3(mp);
    108     PQ[now].Insert(Query(1,1,n,number[mp],number[tail[mp]]).D);
    109     }
    110     Modify(1,1,n,number[now]);
    111     if(top[now] == now){
    112     long long data = Query(1,1,n,number[now],number[tail[now]]).L;
    113     if(data > 0 && fa[now]) TOT[fa[now]]+=data; 
    114     }
    115 }
    116 
    117 void work(){
    118     dfs1(1,0,1);
    119     dfs2(1,1);
    120     dfs3(1);
    121     for(int i=1;i<=m;i++){
    122     char ch = readchar();
    123     if(ch == 'M'){
    124         int x,y; scanf("%d%d",&x,&y);
    125         stack<int> sta; int now = top[x];
    126         while(fa[now]) sta.push(now),now = top[fa[now]];
    127         while(!sta.empty()){
    128         int mp = sta.top();sta.pop();
    129         node res = Query(1,1,n,number[mp],number[tail[mp]]);
    130         PQ[fa[mp]].Erase(res.D);
    131         if(res.L > 0) TOT[fa[mp]]-=res.L;
    132         Modify(1,1,n,number[fa[mp]]);
    133         }
    134         now = x; v[x] = y;
    135         while(now){
    136         Modify(1,1,n,number[now]);
    137         now = top[now];
    138         node res = Query(1,1,n,number[now],number[tail[now]]);
    139         if(res.L > 0 && fa[now]) TOT[fa[now]]+=res.L;
    140         PQ[fa[now]].Insert(res.D);
    141         now= fa[now];
    142         }
    143     }else{
    144         int x; scanf("%d",&x);
    145         long long ans = Query(1,1,n,number[x],number[tail[x]]).D;
    146         printf("%lld
    ",ans);
    147     }
    148     }
    149 }
    150 
    151 int main(){
    152     read();
    153     work();
    154     return 0;
    155 }
  • 相关阅读:
    42. Trapping Rain Water
    223. Rectangle Area
    645. Set Mismatch
    541. Reverse String II
    675. Cut Off Trees for Golf Event
    安装 VsCode 插件安装以及配置
    向上取整 向下取整 四舍五入 产生100以内随机数
    JS 判断是否为数字 数字型特殊值
    移动端初始配置,兼容不同浏览器的渲染内核
    Flex移动布局中单行和双行布局的区别以及使用
  • 原文地址:https://www.cnblogs.com/Menhera/p/9163493.html
Copyright © 2011-2022 走看看