bzoj 2631: tree
来源:互联网 发布:数据圈付费社区 编辑:程序博客网 时间:2024/06/07 12:48
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行,每行描述一个操作
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
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
用LCT维护即可
注意加法和乘法标记合并时候的顺序
用long long存储结果结果TLE了
发现Mod^2<unsigned int
所以用unsigned int存就可以过了
#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<algorithm>using namespace std;int n;unsigned int mod=51061;struct line{ int s,t;}a[100001];struct tree{ int l,r; int fa; int rev; unsigned int sz,val,tag,tagx; bool rt;}tr[800001];unsigned int val[200001];tree nx;inline void update_rev(int x){ if(x==0) return ; int t=tr[x].l; tr[x].l=tr[x].r; tr[x].r=t; tr[x].rev^=1;}inline void push_up(int x){ tr[x].sz=(tr[tr[x].l].sz+tr[tr[x].r].sz+1)%mod; tr[x].val=(tr[tr[x].l].val+tr[tr[x].r].val+val[x])%mod;}inline void push_down(int x){ if(tr[x].rev) { update_rev(tr[x].l); update_rev(tr[x].r); tr[x].rev=0; } val[tr[x].l]=(val[tr[x].l]*tr[x].tagx)%mod; val[tr[x].r]=(val[tr[x].r]*tr[x].tagx)%mod; tr[tr[x].l].val=tr[tr[x].l].val*tr[x].tagx%mod; tr[tr[x].r].val=tr[tr[x].r].val*tr[x].tagx%mod; tr[tr[x].l].tag=(tr[tr[x].l].tag*tr[x].tagx)%mod; tr[tr[x].r].tag=(tr[tr[x].r].tag*tr[x].tagx)%mod; tr[tr[x].l].tagx=(tr[tr[x].l].tagx*tr[x].tagx)%mod; tr[tr[x].r].tagx=(tr[tr[x].r].tagx*tr[x].tagx)%mod; tr[x].tagx=1; val[tr[x].l]=(val[tr[x].l]+tr[x].tag)%mod; val[tr[x].r]=(val[tr[x].r]+tr[x].tag)%mod; tr[tr[x].l].val=(tr[tr[x].l].val+tr[x].tag*tr[tr[x].l].sz%mod)%mod; tr[tr[x].r].val=(tr[tr[x].r].val+tr[x].tag*tr[tr[x].r].sz%mod)%mod; tr[tr[x].l].tag=(tr[tr[x].l].tag+tr[x].tag)%mod; tr[tr[x].r].tag=(tr[tr[x].r].tag+tr[x].tag)%mod; tr[x].tag=0;}inline void push(int x){ if(!tr[x].rt) push(tr[x].fa); push_down(x);}inline void zig(int x){ tr[0]=nx; int t=tr[x].l; tr[x].l=tr[t].r; tr[tr[t].r].fa=x; tr[t].r=x; tr[t].fa=tr[x].fa; tr[x].fa=t; if(tr[x].rt) { tr[x].rt=false; tr[t].rt=true; } else { if(x==tr[tr[t].fa].l) tr[tr[t].fa].l=t; else tr[tr[t].fa].r=t; } push_up(x);}inline void zag(int x){ tr[0]=nx; int t=tr[x].r; tr[x].r=tr[t].l; tr[tr[t].l].fa=x; tr[t].l=x; tr[t].fa=tr[x].fa; tr[x].fa=t; if(tr[x].rt) { tr[x].rt=false; tr[t].rt=true; } else { if(x==tr[tr[t].fa].l) tr[tr[t].fa].l=t; else tr[tr[t].fa].r=t; } push_up(x);}inline void splay(int x){ push(x); while(!tr[x].rt) { int y=tr[x].fa,z=tr[y].fa; if(tr[y].rt) { if(x==tr[y].l) zig(y); else zag(y); } else if(y==tr[z].l) { if(x==tr[y].l){zig(z);zig(y);} else{zag(y);zig(z);} } else { if(x==tr[y].r){zag(z);zag(y);} else{zig(y);zag(z);} } } push_up(x);}inline void access(int x){ int y=0; while(x!=0) { splay(x); tr[tr[x].r].rt=true; tr[x].r=y; tr[y].rt=false; push_up(x); y=x; x=tr[x].fa; }}inline int findroot(int x){ access(x); splay(x); while(tr[x].l!=0) x=tr[x].l; return x;}inline bool judge(int s,int t){ s=findroot(s); t=findroot(t); if(s==t) return true; return false;}inline void mroot(int x){// push_up(x); access(x); splay(x); update_rev(x);}inline void link(int s,int t){ if(judge(s,t)) return ; mroot(s); tr[s].fa=t; //access(s);}inline void cut(int s,int t){ if(s==t||!judge(s,t)) return ; mroot(s); access(t); splay(t); tr[tr[t].l].fa=0; tr[tr[t].l].rt=true; tr[t].l=0; push_up(t);}inline int ask(int x,int y){ mroot(x); access(y); splay(y); return (tr[tr[y].l].val+val[y])%mod;}inline int add1(int x,int y,unsigned int xx){ mroot(x); access(y); splay(y); val[y]=(val[y]+xx)%mod; val[tr[y].l]=(val[tr[y].l]+xx)%mod; tr[tr[y].l].val=(tr[tr[y].l].val+tr[tr[y].l].sz*xx%mod)%mod; tr[tr[y].l].tag=(tr[tr[y].l].tag+xx)%mod; push_up(y); /*tr[tr[y].l].tag=(tr[tr[y].l].tag+xx)%mod; tr[tr[y].r].tag=(tr[tr[y].r].tag+xx)%mod;*/}inline int add2(int x,int y,unsigned int xx){ mroot(x); access(y); splay(y); val[y]=(val[y]*xx)%mod; val[tr[y].l]=(val[tr[y].l]*xx)%mod; tr[tr[y].l].val=tr[tr[y].l].val*xx%mod; tr[tr[y].l].tag=(tr[tr[y].l].tag*xx)%mod; tr[tr[y].l].tagx=(tr[tr[y].l].tagx*xx)%mod; push_up(y); /* tr[tr[y].l].tagx=(tr[tr[y].l].tagx*xx)%mod; tr[tr[y].r].tagx=(tr[tr[y].r].tagx*xx)%mod;*/}int main(){// freopen("data.in","r",stdin);// freopen("data.out","w",stdout); int m; scanf("%d%d",&n,&m); int i; int s,t,x; for(i=1;i<=n-1;i++) scanf("%d%d",&a[i].s,&a[i].t); for(i=1;i<=n;i++) { val[i]=1; tr[i].val=val[i]; tr[i].sz=1; tr[i].rt=true; tr[i].tagx=1; } for(i=1;i<=n-1;i++) link(a[i].s,a[i].t); char xx[11]; int s1,t1; for(i=1;i<=m;i++) { scanf("%s",xx); if(xx[0]=='+') { scanf("%d%d%d",&s,&t,&s1); add1(s,t,s1); } else if(xx[0]=='-') { scanf("%d%d%d%d",&s,&t,&s1,&t1); cut(s,t); link(s1,t1); } else if(xx[0]=='*') { scanf("%d%d%d",&s,&t,&s1); add2(s,t,s1); } else { scanf("%d%d",&s,&t); printf("%u\n",ask(s,t)); } } return 0;}
0 0
- bzoj 2631: tree
- BZOJ 2631 tree LCT
- BZOJ 2631 TREE
- 【LCT】BZOJ 2631:tree
- bzoj 2631 tree
- BZOJ 2631 Tree LCT
- BZOJ 2631 tree
- BZOJ 2631: tree
- BZOJ 2631: tree Link_Cut_Tree
- BZOJ 2631 tree LCT
- 【BZOJ 2631】tree LCT
- BZOJ 2631 tree
- bzoj 2631 tree
- BZOJ 2631: tree LCT
- bzoj 2631: tree LCT
- BZOJ 2631 Tree Link-Cut-Tree(LCT)
- BZOJ-2631 tree Link-Cut-Tree
- bzoj 2631 Tree [Link-Cut Tree]
- unity内部float类型转换string类型只保留整数部分
- 数学中国体力值
- Python笔记——01模块安装方法
- java加密解密工具类
- PHP知识积累
- bzoj 2631: tree
- spring中的default-autowire="byName"
- Qt5中文乱码
- 4.21
- Wpa_supplicant的应用学习
- linux常用命令(1):cd命令
- UITableView的性能优化
- Swift中的问号?和感叹号!
- C++静态库与动态库