zoukankan      html  css  js  c++  java
  • COGS2608 [河南省队2016]无根树

    传送门

    这题大概就是传说中的动态树形DP了吧,学习了一波……

    首先,对于没有修改的情况,不难想到树形DP,定义$f_i$表示强制必须选$i$且只能再选$i$的子树中的点的最优解,易得转移方程$f_i=sum_{j是i的儿子}max{f_j,0}+w_i$,最终答案即为$max{f_i}$。

    现在我们不仅需要求出答案,还要在每次修改之后快速计算新的答案。借鉴陈俊锟的论文,可以用树剖来做这道题,那么我们只需要对每条链动态维护答案即可,最后用一个全局堆维护每条链的答案就可以了。

    我们可以重新定义$f_i$表示只考虑$i$以及轻边连出去的子树的最优解,并用线段树维护重链,不难看出每条链的答案就是链上所有点的$f$值的最大子段和。那么直接用线段树维护最大子段和即可,预处理$O(n)$,单次修改$O(log^2 n)$,查询$O(1)$。

    细节不是很多,当然愿意看代码也行。

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #include<vector>
      5 #include<queue>
      6 using namespace std;
      7 const int maxn=100010;
      8 struct binary_heap{
      9     priority_queue<int>q1,q2;
     10     binary_heap(){}
     11     void push(int x){q1.push(x);}
     12     void erase(int x){q2.push(x);}
     13     int top(){
     14         while(!q2.empty()&&q1.top()==q2.top()){
     15             q1.pop();
     16             q2.pop();
     17         }
     18         return q1.top();
     19     }
     20 }heap;
     21 void dfs1(int);
     22 void dfs2(int);
     23 void modify(int,int);
     24 void build(int,int,int&);
     25 void modify(int,int,int);
     26 void refresh(int);
     27 vector<int>G[maxn];
     28 int sum[maxn<<2],maxsum[maxn<<2],prefix[maxn<<2],suffix[maxn<<2],lc[maxn<<2],rc[maxn<<2],root[maxn],cnt=0;
     29 int p[maxn],size[maxn],d[maxn],dfn[maxn],finish[maxn],tim=0,son[maxn],top[maxn],len[maxn];
     30 int f[maxn],a[maxn],w[maxn];
     31 int n,m,t,k;
     32 int main(){
     33     freopen("nortree.in","r",stdin);
     34     freopen("nortree.out","w",stdout);
     35     int __size__=128<<20;
     36     char *__p__=(char*)malloc(__size__)+__size__;
     37     __asm__("movl %0, %%esp
    "::"r"(__p__));
     38     scanf("%d%d",&n,&m);
     39     for(int i=1;i<=n;i++)scanf("%d",&w[i]);
     40     for(int i=1,x,y;i<n;i++){
     41         scanf("%d%d",&x,&y);
     42         G[x].push_back(y);
     43         G[y].push_back(x);
     44     }
     45     dfs1(1);
     46     dfs2(1);
     47     while(m--){
     48         int d;
     49         scanf("%d",&d);
     50         if(d==1){
     51             int x,z;
     52             scanf("%d%d",&x,&z);
     53             modify(x,z);
     54         }
     55         else printf("%d
    ",heap.top());
     56     }
     57     return 0;
     58 }
     59 void dfs1(int x){
     60     size[x]=1;
     61     d[x]=d[p[x]]+1;
     62     for(int i=0;i<(int)G[x].size();i++)if(G[x][i]!=p[x]){
     63         p[G[x][i]]=x;
     64         dfs1(G[x][i]);
     65         size[x]+=size[G[x][i]];
     66         if(size[G[x][i]]>size[son[x]])son[x]=G[x][i];
     67     }
     68 }
     69 void dfs2(int x){
     70     if(x==son[p[x]])top[x]=top[p[x]];
     71     else top[x]=x;
     72     dfn[x]=++tim;
     73     f[x]=w[x];
     74     if(son[x])dfs2(son[x]);
     75     for(int i=0;i<(int)G[x].size();i++)if(G[x][i]!=p[x]&&G[x][i]!=son[x]){
     76         dfs2(G[x][i]);
     77         f[x]+=max(prefix[root[G[x][i]]],0);
     78     }
     79     finish[x]=tim;
     80     if(top[x]==x){
     81         int cnt=0,y=x;
     82         while(y){
     83             a[++cnt]=f[y];
     84             y=son[y];
     85         }
     86         len[x]=cnt;
     87         build(1,len[x],root[x]);
     88         heap.push(maxsum[root[x]]);
     89     }
     90 }
     91 void modify(int x,int z){
     92     f[x]+=z-w[x];
     93     w[x]=z;
     94     while(x){
     95         if(p[top[x]])f[p[top[x]]]-=prefix[root[top[x]]];
     96         heap.erase(maxsum[root[top[x]]]);
     97         t=d[x]-d[top[x]]+1;
     98         k=f[x];
     99         modify(1,len[top[x]],root[top[x]]);
    100         if(p[top[x]])f[p[top[x]]]+=prefix[root[top[x]]];
    101         heap.push(maxsum[root[top[x]]]);
    102         x=p[top[x]];
    103     }
    104 }
    105 void build(int l,int r,int &rt){
    106     rt=++cnt;
    107     if(l==r){
    108         sum[rt]=a[l];
    109         maxsum[rt]=prefix[rt]=suffix[rt]=max(a[l],0);
    110         return;
    111     }
    112     int mid=(l+r)>>1;
    113     build(l,mid,lc[rt]);
    114     build(mid+1,r,rc[rt]);
    115     refresh(rt);
    116 }
    117 void modify(int l,int r,int rt){
    118     if(l==r){
    119         sum[rt]=k;
    120         maxsum[rt]=prefix[rt]=suffix[rt]=max(k,0);
    121         return;
    122     }
    123     int mid=(l+r)>>1;
    124     if(t<=mid)modify(l,mid,lc[rt]);
    125     else modify(mid+1,r,rc[rt]);
    126     refresh(rt);
    127 }
    128 void refresh(int rt){
    129     sum[rt]=sum[lc[rt]]+sum[rc[rt]];
    130     maxsum[rt]=max(max(maxsum[lc[rt]],maxsum[rc[rt]]),suffix[lc[rt]]+prefix[rc[rt]]);
    131     prefix[rt]=max(prefix[lc[rt]],sum[lc[rt]]+prefix[rc[rt]]);
    132     suffix[rt]=max(suffix[rc[rt]],sum[rc[rt]]+suffix[lc[rt]]);
    133 }
    View Code
  • 相关阅读:
    2016012061 小学四则运算练习软件项目报告
    阅读《构建之法》的几点思考
    软件工程之我见
    作业五
    结对作业
    第4.17章读书笔记
    week_2 四则运算
    第1.2.16章读书笔记
    我与软件工程
    团队项目Alpha冲刺阶段之学习总结
  • 原文地址:https://www.cnblogs.com/hzoier/p/6863850.html
Copyright © 2011-2022 走看看