zoukankan      html  css  js  c++  java
  • BZOJ4712: 洪水(树链剖分维护Dp)

    Description

    小A走到一个山脚下,准备给自己造一个小屋。这时候,小A的朋友(op,又叫管理员)打开了创造模式,然后飞到
    山顶放了格水。于是小A面前出现了一个瀑布。作为平民的小A只好老实巴交地爬山堵水。那么问题来了:我们把这
    个瀑布看成是一个n个节点的树,每个节点有权值(爬上去的代价)。小A要选择一些节点,以其权值和作为代价将
    这些点删除(堵上),使得根节点与所有叶子结点不连通。问最小代价。不过到这还没结束。小A的朋友觉得这样
    子太便宜小A了,于是他还会不断地修改地形,使得某个节点的权值发生变化。不过到这还没结束。小A觉得朋友做
    得太绝了,于是放弃了分离所有叶子节点的方案。取而代之的是,每次他只要在某个子树中(和子树之外的点完全
    无关)。于是他找到你。

    Input

     输入文件第一行包含一个数n,表示树的大小。

    接下来一行包含n个数,表示第i个点的权值。
    接下来n-1行每行包含两个数fr,to。表示书中有一条边(fr,to)。
    接下来一行一个整数,表示操作的个数。
    接下来m行每行表示一个操作,若该行第一个数为Q,则表示询问操作,后面跟一个参数x,表示对应子树的根;若
    为C,则表示修改操作,后面接两个参数x,to,表示将点x的权值加上to。
    n<=200000,保证任意to都为非负数

    Output

     对于每次询问操作,输出对应的答案,答案之间用换行隔开。

    Sample Input

    4
    4 3 2 1
    1 2
    1 3
    4 2
    4
    Q 1
    Q 2
    C 4 10
    Q 1

    Sample Output

    3
    1
    4

    解题思路:

    代码:

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 #define lll spc<<1
      5 #define rrr spc<<1|1
      6 typedef long long lnt;
      7 const int N=200010;
      8 struct trnt{
      9     lnt minv;
     10     lnt lzt;
     11 }tr[N<<2];
     12 struct pnt{
     13     int hd;
     14     int fa;
     15     int tp;
     16     int dp;
     17     int wgt;
     18     int mxs;
     19     int ind;
     20     lnt val;
     21     lnt f;
     22     lnt sigf;
     23 }p[N];
     24 struct ent{
     25     int twd;
     26     int lst;
     27 }e[N<<1];
     28 int cnt;
     29 int n,m;
     30 int dfn;
     31 int plc[N];
     32 char cmd[100];
     33 void ade(int f,int t)
     34 {
     35     cnt++;
     36     e[cnt].twd=t;
     37     e[cnt].lst=p[f].hd;
     38     p[f].hd=cnt;
     39     return ;
     40 }
     41 void Basic_dfs(int x,int f)
     42 {
     43     p[x].fa=f;
     44     p[x].dp=p[f].dp+1;
     45     p[x].wgt=1;
     46     int maxs=-1;
     47     for(int i=p[x].hd;i;i=e[i].lst)
     48     {
     49         int to=e[i].twd;
     50         if(to==f)
     51             continue;
     52         Basic_dfs(to,x);
     53         p[x].sigf+=p[to].f;
     54         p[x].wgt+=p[to].wgt;
     55         if(maxs<p[to].wgt)
     56         {
     57             maxs=p[to].wgt;
     58             p[x].mxs=to;
     59         }
     60     }
     61     if(!p[x].mxs)
     62         p[x].sigf=0x3f3f3f3f;
     63     p[x].f=std::min(p[x].val,p[x].sigf);
     64     return ;
     65 }
     66 void Build_dfs(int x,int top)
     67 {
     68     if(!x)
     69         return ;
     70     p[x].tp=top;
     71     p[x].ind=++dfn;
     72     plc[dfn]=x;
     73     Build_dfs(p[x].mxs,top);
     74     for(int i=p[x].hd;i;i=e[i].lst)
     75     {
     76         int to=e[i].twd;
     77         if(p[to].ind)
     78             continue;
     79         Build_dfs(to,to);
     80     }
     81     return ; 
     82 }
     83 void pushup(int spc)
     84 {
     85     tr[spc].minv=std::min(tr[lll].minv,tr[rrr].minv);
     86     return ;
     87 }
     88 void add(int spc,lnt v)
     89 {
     90     tr[spc].lzt+=v;
     91     tr[spc].minv-=v;
     92     return ;
     93 }
     94 void pushdown(int spc)
     95 {
     96     if(tr[spc].lzt)
     97     {
     98         add(lll,tr[spc].lzt);
     99         add(rrr,tr[spc].lzt);
    100         tr[spc].lzt=0;
    101     }
    102     return ;
    103 }
    104 void build(int l,int r,int spc)
    105 {
    106     if(l==r)
    107     {
    108         tr[spc].minv=p[plc[l]].val-p[plc[l]].sigf;
    109         return ;
    110     }
    111     int mid=(l+r)>>1;
    112     build(l,mid,lll);
    113     build(mid+1,r,rrr);
    114     pushup(spc);
    115     return ;
    116 }
    117 void update(int l,int r,int pos,int spc,lnt v)
    118 {
    119     if(l==r)
    120     {
    121         add(spc,-v);
    122         return ;
    123     }
    124     int mid=(l+r)>>1;
    125     pushdown(spc);
    126     if(pos<=mid)
    127         update(l,mid,pos,lll,v);
    128     else
    129         update(mid+1,r,pos,rrr,v);
    130     pushup(spc);
    131     return ;
    132 }
    133 int scupdate(int l,int r,int ll,int rr,int spc,lnt v)
    134 {
    135     if(l>rr||ll>r)
    136         return 0;
    137     if(l==r)
    138     {
    139         add(spc,v);
    140         if(tr[spc].minv<=0)
    141             return plc[l];
    142         return 0;
    143     }
    144     if(ll<=l&&r<=rr&&tr[spc].minv>v)
    145     {
    146         add(spc,v);
    147         return 0;
    148     }
    149     int mid=(l+r)>>1;
    150     pushdown(spc);
    151     int plcc=scupdate(mid+1,r,ll,rr,rrr,v);
    152     if(!plcc)
    153         plcc=scupdate(l,mid,ll,rr,lll,v);
    154     pushup(spc);
    155     return plcc;
    156 }
    157 lnt query(int l,int r,int pos,int spc)
    158 {
    159     if(l==r)
    160         return tr[spc].minv;
    161     int mid=(l+r)>>1;
    162     pushdown(spc);
    163     if(pos<=mid)
    164         return query(l,mid,pos,lll);
    165     return query(mid+1,r,pos,rrr);
    166 }
    167 void Update(int x,lnt v)
    168 {
    169     if(v<=0||!x)
    170         return ;
    171     while(x)
    172     {
    173         int tp=scupdate(1,n,p[p[x].tp].ind,p[x].ind,1,v);
    174         if(!tp)
    175             x=p[p[x].tp].fa;
    176         else{
    177             Update(p[tp].fa,query(1,n,p[tp].ind,1)+v);
    178             return ;
    179         }
    180     }
    181 }
    182 int main()
    183 {
    184     scanf("%d",&n);
    185     for(int i=1;i<=n;i++)
    186         scanf("%d",&p[i].val);
    187     for(int i=1;i<n;i++)
    188     {
    189         int a,b;
    190         scanf("%d%d",&a,&b);
    191         ade(a,b);
    192         ade(b,a);
    193     }
    194     Basic_dfs(1,1);
    195     Build_dfs(1,1);
    196     build(1,n,1);
    197     scanf("%d",&m);
    198     while(m--)
    199     {
    200         scanf("%s",cmd+1);
    201         if(cmd[1]=='Q')
    202         {
    203             int x;
    204             scanf("%d",&x);
    205             printf("%lld
    ",std::min(p[x].val,p[x].val-query(1,n,p[x].ind,1)));
    206         }else{
    207             int x,v;
    208             scanf("%d%d",&x,&v);
    209             if(!v)
    210                 continue;
    211             p[x].val+=v;
    212             update(1,n,p[x].ind,1,v);
    213             lnt tmp=p[x].val-query(1,n,p[x].ind,1);
    214             p[x].f=std::min(p[x].val,tmp);
    215             Update(p[x].fa,p[x].f+v-p[x].val);
    216         }
    217     }    
    218     return 0;
    219 }
  • 相关阅读:
    void类型和void *指针类型(网上摘抄总结)【转】
    微信小程序中的canvas基础应用
    Google Interview University 一套完整的学习手册帮助自己准备 Google 的面试
    git使用教程(详细)
    Vue下载依赖遇到的一些bug
    原生Javascript客户端表单验证
    ASP MVC 后台控制器弹出框提示
    网页URLJs传值传值传值传值传值问题
    从零开始,搭建博客系统MVC5+EF6搭建框架(1),EF Code frist、实现泛型数据仓储以及业务逻辑
    弹出提示框,在跳转
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10205803.html
Copyright © 2011-2022 走看看