zoukankan      html  css  js  c++  java
  • 动态dp

    bzoj5210: 最大连通子块和

    口胡的弱智型题解:

    $f_x$表示$x$的子树中,与$x$联通(或为空集)的最大联通子块和。

    $ans_x$表示$x$的子树中,最大联通子块和。

    $y is son of x$

    $f_x=max(0,sum f_y+v_x)$

    $ans_x=max(f_x,ans_y)$

    不带修改的话一次树dp即可。

    带修改的,考虑用树剖维护,

    设$g_x=v_x+sum_{y|y是x的轻儿子}f_y$,$son_x$表示$x$的重儿子

    $f_x=max(0,g_x+f_{son_x})$

    试着看一条重链,链底的$f_x=g_x=max(0,v_x)$,往上$f_x=max(0,g_x+f_{son_x})$。这就是一个以x开头的最大连续子段和,可以用线段树维护!

    也就是说,在线段树上存下每个x的g就可以查到每个x对应的f了。而修改的时候,重链上线段树上修改g,再跳到上一条重链继续修改即可。(第一次修改g是因为v的改变,往上跳修改是因为$f_{轻儿子}$的改变)

    再考虑ans的维护。如果用$s_x$表示轻儿子的$ans$的最大值

    $ans_x=max(s_x,s_{son_x},f_x)$

    $s_x$和$g_x$的差别在于取最大值在修改时不好处理,所以$s_x$不能是一个值(轻儿子的$ans$的最大值)而是一个set(存所有轻儿子的$ans$值),这样s和g的修改就一样操作了。

    然后这个$s_x$可以直接放在线段树上,x的节点上,这样很容易取最大值。
    而重儿子的ans,是一段最大连续子段最短和,那么对于x来说,这条重链上的所有f,也就是任意位置开始的一段最大连续子段和。这个就也可以用线段树维护,并可以和$s_x$用同一个值维护,就可以在线段树上直接查到x的ans了。

      1 //Achen
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<vector>
      7 #include<cstdio>
      8 #include<queue>
      9 #include<cmath>
     10 #include<set>
     11 #include<map>
     12 #define Formylove return 0
     13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
     14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
     15 const int N=400007; 
     16 typedef long long LL;
     17 typedef double db;
     18 using namespace std;
     19 int n,m;
     20 LL v[N];
     21 char op[5];
     22 
     23 template<typename T>void read(T &x)  {
     24     char ch=getchar(); x=0; T f=1;
     25     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
     26     if(ch=='-') f=-1,ch=getchar();
     27     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
     28 }
     29 
     30 struct sg {
     31     LL sum,sl,sr,sm;
     32     friend sg operator +(const sg&ls,const sg&rs) {
     33         sg a;
     34         a.sum=ls.sum+rs.sum;
     35         a.sl=max(ls.sl,ls.sum+rs.sl);
     36         a.sr=max(rs.sr,rs.sum+ls.sr);
     37         a.sm=max(max(ls.sm,rs.sm),ls.sr+rs.sl);
     38         return a;
     39     }
     40 }tr[N<<2];
     41 multiset<LL>s[N];
     42 
     43 #define lc x<<1
     44 #define rc ((x<<1)|1)
     45 #define mid ((l+r)>>1)
     46 sg qry(int x,int l,int r,int ql,int qr) {
     47     if(l>=ql&&r<=qr) return tr[x];
     48     if(qr<=mid) return qry(lc,l,mid,ql,qr);
     49     if(ql>mid) return qry(rc,mid+1,r,ql,qr);
     50     return qry(lc,l,mid,ql,qr)+qry(rc,mid+1,r,ql,qr);
     51 }
     52 
     53 void update(int x,int l,int r,int pos,LL g,LL mg) {
     54     if(l==r) {
     55         tr[x].sum=g;
     56         tr[x].sl=tr[x].sr=max(0LL,g);
     57         tr[x].sm=max(mg,g);
     58         return ;
     59     }
     60     if(pos<=mid) update(lc,l,mid,pos,g,mg);
     61     else update(rc,mid+1,r,pos,g,mg);
     62     tr[x]=tr[lc]+tr[rc];
     63 }
     64 
     65 int ecnt,fir[N],nxt[N<<1],to[N<<1];
     66 void add(int u,int v) {
     67     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
     68     nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
     69 }
     70 
     71 int R[N],fa[N],sz[N];
     72 void dfs(int x,int Fa) {
     73     sz[x]=1;
     74     fa[x]=Fa;
     75     R[x]=R[Fa]+1;
     76     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=Fa) {
     77         dfs(to[i],x);
     78         sz[x]+=sz[to[i]];
     79     } 
     80 }
     81 
     82 int top[N],ed[N],dfk,tid[N],tot;
     83 LL ftf[N],stf[N];
     84 void DFS(int x,int Top) {
     85     tid[x]=++tot;
     86     top[x]=Top;
     87     ed[Top]=x;
     88     int mson=0;
     89     for(int i=fir[x];i;i=nxt[i]) 
     90         if(to[i]!=fa[x]&&(!mson||sz[to[i]]>sz[mson]))
     91             mson=to[i];
     92     if(!mson) {
     93         update(1,1,n,tid[x],v[x],0);
     94         return;
     95     }
     96     DFS(mson,Top);
     97     LL gx=v[x],mg=0;
     98     for(int i=fir[x];i;i=nxt[i]) 
     99         if(to[i]!=fa[x]&&to[i]!=mson) {
    100             DFS(to[i],to[i]);
    101             sg tp=qry(1,1,n,tid[to[i]],tid[ed[top[to[i]]]]);
    102             gx+=tp.sl; 
    103             mg=max(mg,tp.sm);
    104             s[x].insert(tp.sm);
    105             ftf[to[i]]=tp.sl;
    106             stf[to[i]]=tp.sm;
    107         }
    108     update(1,1,n,tid[x],gx,mg);
    109 }
    110 
    111 void change(int x,LL y) {
    112     sg tp=qry(1,1,n,tid[x],tid[x]),tpz;
    113     LL gx=tp.sum-v[x]+y; v[x]=y;
    114     LL mg=0; if(!s[x].empty()) mg=*s[x].rbegin();
    115     update(1,1,n,tid[x],gx,mg);
    116     for(;;) {
    117         int z=fa[top[x]];
    118         if(!z) break;
    119         tp=qry(1,1,n,tid[top[x]],tid[ed[top[x]]]);
    120         tpz=qry(1,1,n,tid[z],tid[z]);
    121         LL gx=tpz.sum-ftf[top[x]]+tp.sl;
    122         s[z].erase(s[z].find(stf[top[x]]));
    123         s[z].insert(tp.sm); 
    124         ftf[top[x]]=tp.sl;
    125         stf[top[x]]=tp.sm;
    126         LL mg=*s[z].rbegin();
    127         update(1,1,n,tid[z],gx,mg);
    128         x=z;
    129     }
    130 }
    131 
    132 int main() {
    133 #ifdef ANS
    134     freopen(".in","r",stdin);
    135     freopen(".out","w",stdout);
    136 #endif
    137     read(n); read(m);
    138     For(i,1,n) read(v[i]);
    139     For(i,2,n) {
    140         int u,v;
    141         read(u); read(v);
    142         add(u,v);
    143     }
    144     dfs(1,0);
    145     DFS(1,1);
    146     For(ti,1,m) {
    147         scanf("%s",op);
    148         int x; LL y;
    149         if(op[0]=='M') {
    150             read(x); read(y);
    151             change(x,y);
    152         }
    153         else {
    154             read(x);
    155             sg tp=qry(1,1,n,tid[x],tid[ed[top[x]]]);
    156             LL ans=tp.sm;
    157             printf("%lld
    ",ans);
    158         }
    159     }
    160     Formylove;
    161 }
    View Code

    bzoj4712: 洪水

    本来想写题解,但是代码里面注释得已经非常详细了,就放一个别人的题解

    这种修改操作只有权值加的好像很套路呀。

      1 //Achen
      2 #include<algorithm>
      3 #include<iostream>
      4 #include<cstring>
      5 #include<cstdlib>
      6 #include<vector>
      7 #include<cstdio>
      8 #include<queue>
      9 #include<cmath>
     10 #include<set>
     11 #include<map>
     12 #define Formylove return 0
     13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
     14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
     15 const int N=400007; 
     16 typedef long long LL;
     17 typedef double db;
     18 using namespace std;
     19 int n,m;
     20 char op[5];
     21 
     22 template<typename T>void read(T &x)  {
     23     char ch=getchar(); x=0; T f=1;
     24     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
     25     if(ch=='-') f=-1,ch=getchar();
     26     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
     27 }
     28 
     29 LL v[N],sg[N<<2],lz[N<<2];
     30 #define lc x<<1
     31 #define rc ((x<<1)|1)
     32 #define mid ((l+r)>>1)
     33 void down(int x,int l_len,int r_len) {
     34     if(!lz[x]) return;
     35     sg[lc]+=lz[x]; lz[lc]+=lz[x];
     36     sg[rc]+=lz[x]; lz[rc]+=lz[x];
     37     lz[x]=0;
     38 }
     39 
     40 LL qry(int x,int l,int r,int ql,int qr) {
     41     if(l>=ql&&r<=qr) return sg[x];
     42     down(x,mid-l+1,r-mid);
     43     if(qr<=mid) return qry(lc,l,mid,ql,qr);
     44     if(ql>mid) return qry(rc,mid+1,r,ql,qr);
     45     return min(qry(lc,l,mid,ql,qr),qry(rc,mid+1,r,ql,qr));
     46 }
     47 
     48 int lef[N];
     49 void update(int x,int l,int r,int ql,int qr,LL v) {
     50     if(l>=ql&&r<=qr) { 
     51         if(l==r&&lef[l]) return;
     52         sg[x]+=v; if(l!=r) lz[x]+=v; return;
     53     }
     54     down(x,mid-l+1,r-mid);
     55     if(ql<=mid) update(lc,l,mid,ql,qr,v);
     56     if(qr>mid) update(rc,mid+1,r,ql,qr,v);
     57     sg[x]=min(sg[lc],sg[rc]);
     58 }
     59 
     60 int ecnt,fir[N],nxt[N<<1],to[N<<1];
     61 void add(int u,int v) {
     62     nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
     63     nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
     64 }
     65 
     66 int fa[N],sz[N];
     67 void dfs(int x,int Fa) {
     68     sz[x]=1;
     69     fa[x]=Fa;
     70     for(int i=fir[x];i;i=nxt[i]) if(to[i]!=Fa) {
     71         dfs(to[i],x);
     72         sz[x]+=sz[to[i]];
     73     } 
     74 }
     75 
     76 int top[N],tid[N],ftid[N],tot;
     77 void DFS(int x,int Top) {
     78     tid[x]=++tot;
     79     ftid[tot]=x;
     80     top[x]=Top;
     81     int mson=0;
     82     for(int i=fir[x];i;i=nxt[i]) 
     83         if(to[i]!=fa[x]&&(!mson||sz[to[i]]>sz[mson]))
     84             mson=to[i];
     85     if(!mson) {
     86         lef[tid[x]]=1;
     87         update(1,1,n,tid[x],tid[x],0); //设叶子 v[x]==g[x]
     88         return;
     89     }
     90     LL gx=0;
     91     DFS(mson,Top);
     92     LL tp=qry(1,1,n,tid[mson],tid[mson]);
     93     gx+=min(v[mson],v[mson]-tp);
     94     for(int i=fir[x];i;i=nxt[i]) 
     95         if(to[i]!=fa[x]&&to[i]!=mson) {
     96             DFS(to[i],to[i]);
     97             LL tp=qry(1,1,n,tid[to[i]],tid[to[i]]);
     98             gx+=min(v[to[i]],v[to[i]]-tp);
     99         }
    100     update(1,1,n,tid[x],tid[x],v[x]-gx);
    101 }
    102 
    103 void change(int x,LL y) {
    104     //v[x]增加了y 
    105     LL tp=qry(1,1,n,tid[x],tid[x]);
    106     LL gx=lef[tid[x]]?v[x]+y:v[x]-tp;//如果是叶子,g始终等于v!!!! 
    107     update(1,1,n,tid[x],tid[x],y); //v-g增加y 
    108     if(gx<=v[x]) { //原来选g,现在仍选g 
    109         v[x]+=y; return;
    110     }
    111     LL plus;
    112     if(v[x]+y<=gx) plus=y; //原来选v,现在选仍v,f增加y 
    113     else plus=gx-v[x]; //原来选v,现在选g,f增加g-v 
    114     v[x]+=y;
    115     for(;;) {
    116         //f[x]增加了plus,即g[z]增加了plus 
    117         int z=fa[x];
    118         if(!z) break;
    119         tp=qry(1,1,n,tid[z],tid[z]);
    120         LL gz=v[z]-tp;
    121         update(1,1,n,tid[z],tid[z],-plus);
    122         if(gz>=v[z]) return; //原来选v->g↑,仍选v 
    123         if(v[z]<=gz+plus) plus=v[z]-gz,x=z; //原来选g->现在选v(由g->v最多n+m次,故可以暴力)
    124         else { //原来选g->现在g↑仍选g 
    125             int t=top[z];
    126             int l=tid[t],r=tid[z],rs=r;
    127             while(l<=r) {
    128                 tp=qry(1,1,n,mid,tid[z]);
    129                 if(tp>=plus) rs=mid,r=mid-1;
    130                 else l=mid+1;
    131             }
    132             if(tid[z]>rs) update(1,1,n,rs,tid[z]-1,-plus);
    133             x=ftid[rs];
    134         }
    135     }
    136 }
    137 
    138 int main() {
    139 #ifdef ANS
    140     freopen(".in","r",stdin);
    141     freopen(".out","w",stdout);
    142 #endif
    143     read(n); 
    144     For(i,1,n) read(v[i]);
    145     For(i,2,n) {
    146         int u,v;
    147         read(u); read(v);
    148         add(u,v);
    149     }
    150     dfs(1,0);
    151     DFS(1,1);
    152     read(m);
    153     For(ti,1,m) {
    154         scanf("%s",op);
    155         int x; LL y;
    156         if(op[0]=='C') {
    157             read(x); read(y);
    158             change(x,y);
    159         }
    160         else {
    161             read(x);
    162             LL ans=qry(1,1,n,tid[x],tid[x]);
    163             ans=min(v[x],v[x]-ans);
    164             printf("%lld
    ",ans);
    165         }
    166     }
    167     Formylove;
    168 }
    169 /*
    170 4
    171 4 3 2 1
    172 1 2
    173 1 3
    174 4 2
    175 4
    176 C 4 10
    177 Q 1
    178 */
    View Code
  • 相关阅读:
    Alpha 冲刺 (8/10)
    Alpha 冲刺 (7/10)
    Alpha 冲刺 (6/10)
    团队作业-随堂小测(同学录)
    Alpha 冲刺 (5/10)
    LeetCode-1
    c++向量
    软件工程实践总结作业
    个人作业——软件产品案例分析
    个人技术博客Alpha----Android Studio学习
  • 原文地址:https://www.cnblogs.com/Achenchen/p/9525688.html
Copyright © 2011-2022 走看看