BZOJ3589: 动态树
3589: 动态树
Time Limit: 30 Sec Memory Limit: 1024 MBSubmit: 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
代码:
View Code
各种逗逼。。。
一个暴力的思路是我们每次沿边走然后打上标记,最后输出有标记的点的和。这样是可以过的。
然后我写完之后狂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 }