【国家集训队2012】tree(伍一鸣)
2017-02-19 16:56
375 查看
Description
一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。
Input
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
4
Hint
数据规模:
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5 * 10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5 * 10^4,没有-操作
100%的数据保证,1<=n,q<=10^5,0<=c<=10^4
正解:link-cut tree。
毒瘤数据结构题,调了我一下午。。主要是加和乘的lazy标记,下放时如果是乘,那么加的那个标记也要同乘,并且要先下放乘的标记,再下放加的标记。
一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。
Input
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
4
Hint
数据规模:
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5 * 10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5 * 10^4,没有-操作
100%的数据保证,1<=n,q<=10^5,0<=c<=10^4
正解:link-cut tree。
毒瘤数据结构题,调了我一下午。。主要是加和乘的lazy标记,下放时如果是乘,那么加的那个标记也要同乘,并且要先下放乘的标记,再下放加的标记。
//It is made by wfj_2048~ #include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> #define inf (1<<30) #define r64 (51061) #define N (100010) #define il inline #define RG register #define uint unsigned int #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; uint ch [2],fa ,size ,lazy ,st ,rev1 ,rev2 ,val ,sum ,n,q; char s[5]; il uint gi(){ RG uint x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x; } il void pushdown(RG uint x){ RG uint &l=ch[x][0],&r=ch[x][1]; if (lazy[x]) lazy[x]=0,lazy[l]^=1,lazy[r]^=1,swap(l,r); if (rev2[x]!=1){ (val[l]*=rev2[x])%=r64,(val[r]*=rev2[x])%=r64; (sum[l]*=rev2[x])%=r64,(sum[r]*=rev2[x])%=r64; (rev1[l]*=rev2[x])%=r64,(rev1[r]*=rev2[x])%=r64; (rev2[l]*=rev2[x])%=r64,(rev2[r]*=rev2[x])%=r64,rev2[x]=1; } if (rev1[x]){ (val[l]+=rev1[x])%=r64,(val[r]+=rev1[x])%=r64; (sum[l]+=rev1[x]*(size[l]%r64))%=r64,(sum[r]+=rev1[x]*(size[r]%r64))%=r64; (rev1[l]+=rev1[x])%=r64,(rev1[r]+=rev1[x])%=r64,rev1[x]=0; } return; } il void pushup(RG uint x){ sum[x]=(sum[ch[x][0]]+sum[ch[x][1]]+val[x])%r64; size[x]=size[ch[x][0]]+size[ch[x][1]]+1; return; } il uint isroot(RG uint x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; } il void rotate(RG uint x){ RG uint y=fa[x],z=fa[y],k=ch[y][0]==x; if (!isroot(y)) ch[z][ch[z][1]==y]=x; fa[x]=z; ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y,ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return; } il void splay(RG uint x){ RG uint top=0; st[++top]=x; for (RG uint i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; while (top) pushdown(st[top--]); while (!isroot(x)){ RG uint y=fa[x],z=fa[y]; if (!isroot(y)){ if ((ch[z][0]==y)^(ch[y][0]==x)) rotate(x); else rotate(y); } rotate(x); } return; } il void access(RG uint x){ RG uint t=0; while (x) splay(x),ch[x][1]=t,pushup(x),t=x,x=fa[x]; return; } il void split(RG uint x){ access(x),splay(x); return; } il void makeroot(RG uint x){ split(x),lazy[x]^=1; return; } il void link(RG uint x,RG uint y){ makeroot(x),fa[x]=y; return; } il void cut(RG uint x,RG uint y){ makeroot(x),split(y),ch[y][0]=fa[x]=0,pushup(y); return; } il void add(RG uint x,RG uint y,RG uint v){ makeroot(x),split(y),(rev1[y]+=v)%=r64,(val[y]+=v)%=r64,(sum[y]+=v*(size[y]%r64))%=r64; return; } il void times(RG uint x,RG uint y,RG uint v){ makeroot(x),split(y),(rev1[y]*=v)%=r64,(rev2[y]*=v)%=r64,(val[y]*=v)%=r64,(sum[y]*=v)%=r64; return; } il uint query(RG uint x,RG uint y){ makeroot(x),split(y); return sum[y]; } il void work(){ n=gi(),q=gi(); RG uint u,v,c; for (RG uint i=1;i<=n;++i) sum[i]=val[i]=rev2[i]=size[i]=1; for (RG uint i=1;i<n;++i) u=gi(),v=gi(),link(u,v); for (RG uint i=1;i<=q;++i){ scanf("%s",s); if (s[0]=='+') u=gi(),v=gi(),c=gi(),add(u,v,c); if (s[0]=='-') u=gi(),v=gi(),cut(u,v),u=gi(),v=gi(),link(u,v); if (s[0]=='*') u=gi(),v=gi(),c=gi(),times(u,v,c); if (s[0]=='/'){ u=gi(),v=gi(); printf("%u\n",query(u,v)); } } return; } int main(){ File("tree"); work(); return 0; }
相关文章推荐
- cogs1799 [国家集训队2012]tree(伍一鸣)
- [国家集训队2012]tree(伍一鸣)
- [COGS 1799][国家集训队2012]tree(伍一鸣)
- 数据结构(动态树):[国家集训队2012]tree(伍一鸣)
- 【国家集训队2012】tree(伍一鸣)
- 【国家集训队2012】tree(伍一鸣)
- [国家集训队2012]tree(陈立杰)
- 2012中国国家集训队命题答辩tree(伍一鸣)
- [国家集训队2012]Tree 最小生成树+二分
- 【国家集训队2012】【BZOJ2654】tree
- [国家集训队2012]middle(陈立杰)
- 【2012中山市选】这是一棵树吗?(tree)
- [国家集训队2012]电子对撞机&nbsp;解题…
- 【树形dp】VK Cup 2012 Round 1 D. Distance in Tree
- Bzoj2631:tree(伍一鸣):LCT
- 2012 Multi-University Training Contest 6-1010 hdu4359 Easy Tree DP?
- 树链剖分 JAG Summer 2012 Day 4 D Do use segment tree
- BZOJ2631 tree(伍一鸣);以及标记下传的几点注意事项
- [BZOJ2816][ZJOI2012]网络-Link Cut Tree
- Changes with Chinatree 2012