BZOJ3589: 动态树

3589: 动态树

Time Limit: 30 Sec  Memory Limit: 1024 MB
Submit: 174  Solved: 79
[Submit][Status]

Description

  小明在楼下种了一棵动态树, 该树每天会在某些节点上长出一些果子. 这棵树的根节点为1, 它有n个节点, n-1条边.

  别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件

  事件0:
  这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子.

  事件1:
  小明希望你求出几条树枝上的果子数. 一条树枝其实就是一个从某个节点到根的路径的一段. 每次小明会选定一些树枝, 让你求出在这些树枝上的节点的果子数的和. 注意, 树枝之间可能会重合, 这时重合的部分的节点的果子只要算一次.

  初始时, 每个节点上都没有果子.

Input

  第一行一个整数n(1<=n<=200,000), 即节点数.
  接下来n-1行, 每行两个数字u, v. 表示果子u和果子v之间有一条直接的边. 节点从1开始编号.
  在接下来一个整数nQ(1<=nQ<=200,000), 表示事件.
  最后nQ行, 每行开头要么是0, 要么是1.
  如果是0, 表示这个事件是事件0. 这行接下来的2个整数u, delta表示以u为根的子树中的每个节点长出了delta个果子.
  如果是1, 表示这个事件是事件1. 这行接下来一个整数K(1<=K<=5), 表示这次询问涉及K个树枝. 接下来K对整数u_k, v_k, 每个树枝从节点u_k到节点v_k. 由于果子数可能非常多, 请输出这个数模2^31的结果.

Output

  对于每个事件1, 输出询问的果子数.

Sample Input


5
1 2
2 3
2 4
1 5
3
0 1 1
0 2 3
1 2 3 1 1 4

Sample Output

13

HINT

 1 <= n <= 200,000, 1 <= nQ <= 200,000, K = 5.


生成每个树枝的过程是这样的:先在树中随机找一个节点, 然后在这个节点到根的路径上随机选一个节点, 这两个节点就作为树枝的两端.

Source

题解:
各种逗逼。。。
一个暴力的思路是我们每次沿边走然后打上标记,最后输出有标记的点的和。这样是可以过的。
然后我写完之后狂WA不止。。。
对排了几组发现两个标记下传的顺序搞反了。。。T_T
代码:
  1 #include<cstdio>
  2 
  3 #include<cstdlib>
  4 
  5 #include<cmath>
  6 
  7 #include<cstring>
  8 
  9 #include<algorithm>
 10 
 11 #include<iostream>
 12 
 13 #include<vector>
 14 
 15 #include<map>
 16 
 17 #include<set>
 18 
 19 #include<queue>
 20 
 21 #include<string>
 22 
 23 #define inf 1000000000
 24 
 25 #define maxn 250000+5
 26 
 27 #define maxm 500+100
 28 
 29 #define eps 1e-10
 30 
 31 #define ll long long
 32 
 33 #define pa pair<int,int>
 34 
 35 #define for0(i,n) for(int i=0;i<=(n);i++)
 36 
 37 #define for1(i,n) for(int i=1;i<=(n);i++)
 38 
 39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
 40 
 41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
 42 
 43 #define mod 1000000007
 44 
 45 using namespace std;
 46 
 47 inline int read()
 48 
 49 {
 50 
 51     int x=0,f=1;char ch=getchar();
 52 
 53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
 54 
 55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
 56 
 57     return x*f;
 58 
 59 }
 60 int n,m,q,tot,head[maxn],a[10],b[10],top[maxn],id[maxn][2],son[maxn],dep[maxn],s[maxn],fa[maxn];
 61 struct edge{int go,next;}e[2*maxn];
 62 struct seg{int l,r,tag[2],sum,ret;}t[4*maxn];
 63 inline void insert(int x,int y)
 64 {
 65     e[++tot]=(edge){y,head[x]};head[x]=tot;
 66     e[++tot]=(edge){x,head[y]};head[y]=tot;
 67 }
 68 inline void dfs(int x)
 69 {
 70     s[x]=1;
 71     for(int i=head[x],y;i;i=e[i].next)
 72         if(!dep[y=e[i].go])
 73         {
 74             dep[y]=dep[x]+1;fa[y]=x;
 75             dfs(y);
 76             s[x]+=s[y];
 77             if(s[y]>s[son[x]])son[x]=y;
 78         }
 79 }
 80 inline void dfs2(int x,int chain)
 81 {
 82     id[x][0]=++m;top[x]=chain;
 83     if(son[x])dfs2(son[x],chain);
 84     for(int i=head[x];i;i=e[i].next)if(e[i].go!=son[x]&&e[i].go!=fa[x])dfs2(e[i].go,e[i].go);
 85     id[x][1]=m;
 86 }
 87 inline void pushup(int k)
 88 {
 89     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
 90     t[k].ret=t[k<<1].ret+t[k<<1|1].ret;
 91     //cout<<k<<' '<<t[k].sum<<' '<<t[k].ret<<endl;
 92 }
 93 inline void build(int k,int l,int r)
 94 {
 95     t[k].l=l;t[k].r=r;int mid=(l+r)>>1;t[k].tag[0]=-1;
 96     if(l==r)return;
 97     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
 98 }
 99 inline void same(int k,int z)
100 {
101     t[k].tag[0]=z;t[k].ret=z==1?t[k].sum:0;
102 }
103 inline void update(int k,int z)
104 {
105     t[k].tag[1]+=z;t[k].sum+=(t[k].r-t[k].l+1)*z;
106 }
107 inline void pushdown(int k)
108 {
109     if(t[k].tag[1]){update(k<<1,t[k].tag[1]);update(k<<1|1,t[k].tag[1]);t[k].tag[1]=0;}
110     if(t[k].tag[0]!=-1){same(k<<1,t[k].tag[0]);same(k<<1|1,t[k].tag[0]);t[k].tag[0]=-1;}
111 }
112 inline void change(int k,int x,int y,int z)
113 {
114     if(t[k].tag[0]==z)return;
115     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
116     if(l==x&&r==y){same(k,z);return;}
117     pushdown(k);
118     if(y<=mid)change(k<<1,x,y,z);
119     else if(x>mid)change(k<<1|1,x,y,z);
120     else change(k<<1,x,mid,z),change(k<<1|1,mid+1,y,z);
121     pushup(k);
122 }
123 inline void add(int k,int x,int y,int z)
124 {
125     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
126     if(l==x&&r==y){update(k,z);return;}
127     pushdown(k);
128     if(y<=mid)add(k<<1,x,y,z);
129     else if(x>mid)add(k<<1|1,x,y,z);
130     else add(k<<1,x,mid,z),add(k<<1|1,mid+1,y,z);
131     pushup(k);
132 }
133 inline void solve(int x,int y,int z)
134 {
135     while(top[x]!=top[y])
136     {
137         if(dep[top[x]]<dep[top[y]])swap(x,y);
138         change(1,id[top[x]][0],id[x][0],z);
139         x=fa[top[x]];
140     }
141     if(dep[x]>dep[y])swap(x,y);
142     change(1,id[x][0],id[y][0],z);
143 }
144 
145 int main()
146 
147 {
148 
149     freopen("input.txt","r",stdin);
150 
151     freopen("output.txt","w",stdout);
152 
153     n=read();
154     for1(i,n-1)insert(read(),read());
155     dep[1]=1;dfs(1);dfs2(1,1);
156     build(1,1,n);
157     q=read();
158     while(q--)
159     {
160         int ch=read();m=read();
161         if(!ch)add(1,id[m][0],id[m][1],read());
162         else 
163         {
164             for1(i,m)a[i]=read(),b[i]=read();
165             for1(i,m)solve(a[i],b[i],1);
166             printf("%d\n",t[1].ret&2147483647);
167             for1(i,m)solve(a[i],b[i],0);
168         }
169     }
170 
171     return 0;
172 
173 } 
View Code

 

posted @ 2014-12-04 14:47  ZYF-ZYF  Views(397)  Comments(0Edit  收藏  举报