• bzoj4034 (树链剖分+线段树)


    Problem T2 (bzoj4034 HAOI2015)

    题目大意

      给定一颗树,1为根节点,要求支持三种操作。

      操作 1 :把某个节点 x 的点权增加 a 。

      操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。  

      操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

    解题分析

      练手题。树链剖分+线段树。

    参考程序

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <cmath>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 #define V 100008
      8 #define E 200008
      9 #define lson l,m,rt << 1
     10 #define rson m+1,r,rt << 1 | 1
     11 #define LL long long
     12 
     13 struct line{
     14     int u,v,w,nt;
     15 }eg[E];
     16 int sum,lt[V];
     17 
     18 void adt(int u,int v){
     19     eg[++sum].u=u; eg[sum].v=v; eg[sum].nt=lt[u]; lt[u]=sum;
     20 }
     21 void add(int u,int v){
     22     adt(u,v); adt(v,u);
     23 }
     24 
     25 int size[V],fa[V],dep[V],son[V],w[V],top[V],rk[V];
     26 int n,m,a[V],cnt;
     27 
     28 void dfs_1(int u){
     29     size[u]=1; dep[u]=dep[fa[u]]+1; son[u]=0;
     30     for (int i=lt[u];i;i=eg[i].nt){
     31         int v=eg[i].v;
     32         if (v==fa[u]) continue;
     33         fa[v]=u;
     34         dfs_1(v);
     35         size[u]+=size[v];
     36         if (size[v]>size[son[u]]) son[u]=v;
     37     }
     38 }
     39 
     40 void dfs_2(int u,int tp){
     41     top[u]=tp; w[u]=++cnt; rk[cnt]=u;
     42     if (son[u]) dfs_2(son[u],tp);
     43     for (int i=lt[u];i;i=eg[i].nt){
     44         int v=eg[i].v;
     45         if (v==fa[u] || v==son[u]) continue;
     46         dfs_2(v,v);
     47     }
     48 }
     49 
     50 struct segment_tree{
     51     LL sum[V << 2],lazy[V << 2];
     52     void pushup(int rt){
     53         sum[rt]=sum[rt<<1]+sum[rt<<1|1];
     54     }
     55     void pushdown(int rt,int m){
     56         if (lazy[rt]){
     57             lazy[rt<<1]+=lazy[rt];
     58             lazy[rt<<1|1]+=lazy[rt];
     59             sum[rt<<1]+=lazy[rt] * (m-m/2);
     60             sum[rt<<1|1]+=lazy[rt] * (m/2);
     61             lazy[rt]=0;
     62         }
     63     }
     64     void build(int l,int r,int rt){
     65         lazy[rt]=0;
     66         if (l==r){
     67             sum[rt]=a[rk[l]];
     68             return;
     69         }
     70         int m=(l+r)/2;
     71         build(lson);
     72         build(rson);
     73         pushup(rt);
     74     }
     75     void update(int L,int R,int val,int l,int r,int rt){
     76         if (L<=l && r<=R){
     77             lazy[rt]+=val;
     78             sum[rt]+=1ll*(r-l+1)*val;
     79             return;        
     80         }
     81         pushdown(rt,r-l+1);
     82         int m=(l+r)/2;
     83         if (L <= m) update(L,R,val,lson);
     84         if (m <  R) update(L,R,val,rson);
     85         pushup(rt);
     86     }
     87     LL query(int L,int R,int l,int r,int rt){
     88         if (L<=l && r<=R){
     89             return sum[rt];
     90         }
     91         pushdown(rt,r-l+1);
     92         int m=(l+r)/2;
     93         LL res=0;
     94         if (L <= m) res+=query(L,R,lson);
     95         if (m <  R) res+=query(L,R,rson); 
     96         return res;
     97     } 
     98 }T;
     99 
    100 void change(int x,int y){
    101     LL res=0;
    102     while (top[x]!=top[y]){
    103         if (dep[top[x]]<dep[top[y]]) swap(x,y);
    104         res+=T.query(w[top[x]],w[x],1,n,1);
    105         x=fa[top[x]];
    106     }
    107     if (dep[x]>dep[y]) swap(x,y);
    108     res+=T.query(w[x],w[y],1,n,1);
    109     printf("%lld
    ",res );
    110 }
    111 
    112 int main(){
    113     memset(lt,0,sizeof(lt)); sum=1;
    114     scanf("%d %d",&n,&m);
    115     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    116     for (int i=1;i<n;i++){
    117         int u,v;
    118         scanf("%d %d",&u,&v);
    119         add(u,v);
    120     }
    121     dfs_1(1);
    122     dfs_2(1,1);
    123     T.build(1,n,1);
    124     while (m--){
    125         int x,y,z;
    126         scanf("%d",&x);
    127         if (x==1){
    128             scanf("%d %d",&y,&z);
    129             T.update(w[y],w[y],z,1,n,1);
    130         }
    131         if (x==2){
    132             scanf("%d %d",&y,&z);
    133             T.update(w[y],w[y]+size[y]-1,z,1,n,1);
    134         }
    135         if (x==3){
    136             scanf("%d",&y);
    137             change(1,y);
    138         }
    139     }
    140 }
    View Code

      

  • 相关阅读:
    Java / Android 基于Http的多线程下载的实现
    Java实现敏感词过滤
    java中途强制跳出递归
    Java 并发专题 : Executor详细介绍 打造基于Executor的Web服务器
    Android权限列表
    Java 并发专题 : CyclicBarrier 打造一个安全的门禁系统
    android 开发-系统设置界面的实现
    android 开发-数据存储之共享参数
    android 开发-(Contextual Menu)上下文菜单的实现
    android 开发-ListView与ScrollView事件冲突处理(事件分发机制处理)
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/5727601.html
Copyright © 2020-2023  润新知