[SHOI2012]魔法树

题目传送门

省选D2T3考板子可真是不多见呢。。。。~~~

这题就是一个裸的树链剖分,对于每一个Add操作,维护从u至v的路径,对于每一个Query操作,询问以u为根的子树之和。如果不会树链剖分可以看我的往期博客,具体细节在代码之中就不多赘述了~

下面给出参考代码:

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #define N 400005
  4 #define M 800005
  5 #define lc k*2
  6 #define rc k*2+1
  7 #define mid (l+r)/2
  8 #define int long long
  9 using namespace std;
 10 struct node
 11 {
 12     int l,r,w,tag;
 13 }tree[4*N];
 14 int n,m,r,p,x,y,z;
 15 int v[M],head[M],nxt[M],cnt;
 16 int dep[N],fa[N],son[N],size[N],top[N],seg[N],id;
 17 char q;
 18 int read()
 19 {
 20     int x=0,f=1;char ch=getchar();
 21     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 22     while(ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
 23     return x*f;
 24 }
 25 void add(int a,int b)
 26 {
 27     v[++cnt]=b;
 28     nxt[cnt]=head[a];
 29     head[a]=cnt;
 30 }
 31 void dfs1(int node,int father)
 32 {
 33     dep[node]=dep[father]+1;
 34     fa[node]=father;
 35     size[node]=1;
 36     int maxson=-1;
 37     for(int i=head[node];i;i=nxt[i])
 38     {
 39         int go=v[i];
 40         if(go==father)continue;
 41         dfs1(go,node);
 42         size[node]+=size[go];
 43         if(size[go]>maxson)maxson=size[go],son[node]=go;
 44     }
 45 }
 46 void dfs2(int node,int topfather)
 47 {
 48     seg[node]=++id;
 49     top[node]=topfather;
 50     if(!son[node])return;
 51     dfs2(son[node],topfather);
 52     for(int i=head[node];i;i=nxt[i])
 53     {
 54         int go=v[i];
 55         if(go==fa[node]||go==son[node])continue;
 56         dfs2(go,go);
 57     }
 58 }
 59 void build(int l,int r,int k)
 60 {
 61     tree[k].l=l;tree[k].r=r;
 62     if(l==r)return;
 63     build(l,mid,lc);
 64     build(mid+1,r,rc);
 65 }
 66 void pushdown(int k)
 67 {
 68     tree[lc].tag+=tree[k].tag;
 69     tree[rc].tag+=tree[k].tag;
 70     tree[lc].w+=(tree[lc].r-tree[lc].l+1)*tree[k].tag;
 71     tree[rc].w+=(tree[rc].r-tree[rc].l+1)*tree[k].tag;
 72     tree[k].tag=0;
 73     return;
 74 }
 75 void pushup(int k)
 76 {
 77     tree[k].w=tree[lc].w+tree[rc].w;
 78     return;
 79 }
 80 void add(int x,int y,int k)
 81 {
 82     int l=tree[k].l,r=tree[k].r;
 83     if(l>=x&&r<=y)
 84     {
 85         tree[k].tag+=z;
 86         tree[k].w+=(r-l+1)*z;
 87         return;
 88     }
 89     if(tree[k].tag)pushdown(k);
 90     if(x<=mid)add(x,y,lc);
 91     if(y>mid)add(x,y,rc);
 92     pushup(k);
 93 }
 94 int query(int x,int y,int k)
 95 {
 96     int l=tree[k].l,r=tree[k].r;
 97     if(l>=x&&r<=y)
 98     {
 99         return tree[k].w;
100     }
101     if(tree[k].tag)pushdown(k);
102     int res=0;
103     if(x<=mid)res+=query(x,y,lc);
104     if(y>mid)res+=query(x,y,rc);
105     return res;
106 }
107 void Tadd(int x,int y)
108 {
109     while(top[x]!=top[y])
110     {
111         if(dep[top[x]]<dep[top[y]])swap(x,y);
112         add(seg[top[x]],seg[x],1);
113         x=fa[top[x]];
114     }
115     if(dep[x]>dep[y])swap(x,y);
116     add(seg[x],seg[y],1);
117 }
118 int Treequery(int x)
119 {
120     return query(seg[x],seg[x]+size[x]-1,1);
121 }
122 signed main()
123 {
124     n=read();
125     for(int i=1;i<n;i++)
126     {
127         x=read();y=read();
128         x++;y++;
129         add(x,y);add(y,x);
130     }
131     dfs1(1,0);dfs2(1,1);
132     build(1,n,1);
133     m=read();
134     while(m--)
135     {
136         cin>>q;
137         if(q=='A')
138         {
139             x=read();y=read();z=read();
140             x++;y++;
141             Tadd(x,y);
142         }
143         else
144         {
145             x=read();
146             x++;
147             cout<<Treequery(x)<<endl;
148         }
149     }
150 }
View Code

 

posted @ 2019-07-07 08:26  shao0320  阅读(188)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************