B20J_2836_魔法树_树链剖分+线段树

Posted fcwww

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了B20J_2836_魔法树_树链剖分+线段树相关的知识,希望对你有一定的参考价值。

B20J_2836_魔法树_树链剖分+线段树

题意:

果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u]。初始时,这个果树的每个节点上都没有果子(即0个果子)。

Add u v d

表示将点u和v之间的路径上的所有节点的果子个数都加上d。

Query u

表示当前果树中,以点u为根的子树中,总共有多少个果子?

 

分析:模板题。记录一下x结点的子孙中最后一次出现的位置。

代码:

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 using namespace std;
  5 #define N 100010
  6 #define lson pos<<1
  7 #define rson pos<<1|1
  8 #define LL long long
  9 int head[N],to[N<<1],nxt[N<<1],cnt,n,tot,m;
 10 int dep[N],siz[N],fa[N],son[N],idx[N],top[N],sec[N];
 11 LL t[N<<2],lz[N<<2];
 12 char ch[10];
 13 inline void read(int &x)
 14 {
 15     int f=1;x=0;char s=getchar();
 16     while(s<0||s>9){if(s==-)f=-1;s=getchar();}
 17     while(s>=0&&s<=9){x=(x<<3)+(x<<1)+s-0;s=getchar();}
 18     x*=f;
 19 }
 20 inline void add(int u,int v)
 21 {
 22     to[++cnt]=v;
 23     nxt[cnt]=head[u];
 24     head[u]=cnt;    
 25 }
 26 inline void dfs1(int x,int y)
 27 {
 28     dep[x]=dep[y]+1;
 29     fa[x]=y;
 30     siz[x]=1;
 31     for(int i=head[x];i;i=nxt[i])
 32     {
 33         if(to[i]!=y)
 34         {
 35             dfs1(to[i],x);
 36             siz[to[i]]+=siz[x];
 37             if(siz[to[i]]>siz[son[x]])
 38             {
 39                 son[x]=to[i];
 40             }
 41         }
 42     }
 43 }
 44 inline void dfs2(int x,int t)
 45 {
 46     top[x]=t;
 47     idx[x]=++tot;
 48     if(son[x])dfs2(son[x],t);
 49     for(int i=head[x];i;i=nxt[i])
 50     {
 51         if(to[i]!=fa[x]&&to[i]!=son[x])
 52         {
 53             dfs2(to[i],to[i]);
 54         }
 55     }
 56     sec[x]=tot;
 57 }
 58 inline void pud(int l,int r,int pos,int c)
 59 {
 60     t[pos]+=(r-l+1)*c;
 61     lz[pos]+=c;    
 62 }
 63 inline void up(int l,int r,int x,int y,int z,int pos)
 64 {
 65     if(x<=l&&y>=r)
 66     {
 67         t[pos]+=(r-l+1)*z;
 68         lz[pos]+=z;
 69         return ;
 70     }
 71     int mid=l+r>>1;
 72     if(lz[pos])
 73     {
 74         pud(l,mid,lson,lz[pos]);
 75         pud(mid+1,r,rson,lz[pos]);
 76         lz[pos]=0;    
 77     }
 78     if(x<=mid)up(l,mid,x,y,z,lson);
 79     if(y>mid)up(mid+1,r,x,y,z,rson);
 80     t[pos]=t[lson]+t[rson];
 81 }
 82 inline LL query(int l,int r,int x,int y,int pos)
 83 {
 84     if(x<=l&&y>=r)
 85     {
 86         return t[pos];
 87     }
 88     int mid=l+r>>1;
 89     if(lz[pos])
 90     {
 91         pud(l,mid,lson,lz[pos]);
 92         pud(mid+1,r,rson,lz[pos]);
 93         lz[pos]=0;    
 94     }
 95     LL re=0;
 96     if(x<=mid)re+=query(l,mid,x,y,lson);
 97     if(y>mid)re+=query(mid+1,r,x,y,rson);
 98     return re;
 99 }
100 int main()
101 {
102     read(n);
103     register int x,y,i,z;
104     for(i=1;i<n;++i)
105     {
106         read(x),read(y);
107         add(x+1,y+1);
108         add(y+1,x+1);    
109     }
110     dfs1(1,0);
111     dfs2(1,1);
112     read(m);
113     while(m--)
114     {
115         scanf("%s",ch);
116         if(ch[0]==A)
117         {
118             read(x),read(y),read(z);
119             x++,y++;
120             while(top[x]!=top[y])
121             {
122                 if(dep[top[x]]>dep[top[y]])swap(x,y);
123                 up(1,n,idx[top[y]],idx[y],z,1);
124                 y=fa[top[y]];    
125             }
126             if(dep[x]<dep[y])swap(x,y);
127             up(1,n,idx[y],idx[x],z,1);
128         }
129         else
130         {
131             read(x);
132             x++;
133             printf("%lld\n",query(1,n,idx[x],sec[x],1));
134         }
135     }
136 }

 

以上是关于B20J_2836_魔法树_树链剖分+线段树的主要内容,如果未能解决你的问题,请参考以下文章

B20J_3231_[SDOI2014]旅行_树链剖分+线段树

bzoj2836魔法树 树链剖分+线段树

bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树

[GDOI2016] 疯狂动物园 [树链剖分+可持久化线段树]

树链剖分总结线段树维护

BZOJ_3589_动态树_容斥原理+树链剖分