2631: tree LCT第二题
来源:互联网 发布:otg软件下载 编辑:程序博客网 时间:2024/05/16 07:34
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
权限题差评。。
这题还是一个模板题。。
但是我才第二题就陷入了无限调试,最后发现pushdown写错了
终于知道rev的重要性了
#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>#include<stack>typedef unsigned int Int;using namespace std;const int N=100005;const int MOD=51061;struct qq{ int son[2],fa; bool rev; Int add,mul; Int c;//权值和 Int d;//自己的值 Int tot;//人数 qq bt () { son[0]=son[1]=fa=rev=add=0;mul=1; c=1;d=1;tot=1; };}s[N];int n,q;void cal (int x,int m,int a){ if (x==0) return ; s[x].d=(s[x].d*m+a)%MOD; s[x].c=(s[x].c*m+a*s[x].tot)%MOD; s[x].add=(s[x].add*m+a)%MOD; s[x].mul=(s[x].mul*m)%MOD;}void update (int x)//更新这个节点的信息{ int s1=s[x].son[0],s2=s[x].son[1]; s[x].tot=s[s1].tot+s[s2].tot+1; s[x].c=(s[s1].c+s[s2].c+s[x].d)%MOD;}void Push_down (int x){ int s1=s[x].son[0],s2=s[x].son[1]; if (s[x].rev) { s[x].rev=false; s[s1].rev^=1;s[s2].rev^=1; swap(s[x].son[0],s[x].son[1]); } int m=s[x].mul,a=s[x].add; s[x].mul=1;s[x].add=0; if (m!=1||a!=0){cal(s1,m,a);cal(s2,m,a);}}bool Is_root(int x){ if((s[s[x].fa].son[0]!=x)&&(s[s[x].fa].son[1]!=x)) return true; return false;}void rotate (int x){ int y=s[x].fa,z=s[y].fa; int r,R,f,w; if (s[y].son[0]==x) w=1; else w=0; r=s[x].son[w];R=y; s[R].son[1-w]=r; if (r!=0) s[r].fa=R; r=x;R=z; if (!Is_root(y)) { if (s[R].son[0]==y) s[R].son[0]=r; else s[R].son[1]=r; } if (r!=0) s[r].fa=R; r=y;R=x; s[R].son[w]=r; if (r!=0) s[r].fa=R; update(y);update(x);}stack<int> S;void Preserve (int x){ while (!Is_root(x)) S.push(x),x=s[x].fa;S.push(x); while (!S.empty()) Push_down(S.top()),S.pop();}void Splay (int x){ Preserve(x); while (!Is_root(x)) { int y=s[x].fa,z=s[y].fa; if (!Is_root(y)) { if ((s[y].son[1]==x)==(s[z].son[1]==y)) rotate(y); else rotate(x); } rotate(x); }}void Access (int x){ int last=0; while (x!=0) { Splay(x); s[x].son[1]=last; update(x);/****/ last=x; x=s[x].fa; }}void Make_root (int x){ Access(x); Splay(x); s[x].rev^=1;}void Link (int x,int y){ Make_root(y); s[y].fa=x;}void Split (int x,int y){ Make_root(x); /*for (int u=1;u<=3;u++) printf("%d %d %d %d\n",u,s[u].son[0],s[u].son[1],s[u].fa); printf("\n");*/ Access(y); /*for (int u=1;u<=3;u++) printf("%d %d %d %d\n",u,s[u].son[0],s[u].son[1],s[u].fa);*/ Splay(y);}void Cut (int x,int y){ Split(x,y); s[x].fa=0; s[y].son[0]=0; update(y);}int main(){ scanf("%d%d",&n,&q); for (int u=1;u<=n;u++) s[u].bt(); for (int u=1;u<n;u++) { int x,y; scanf("%d%d",&x,&y); Link(x,y); } while (q--) { char ss[5]; scanf("%s",ss); if (ss[0]=='+')//都加上这个数 { int x,y,c; scanf("%d%d%d",&x,&y,&c); Split(x,y);cal(y,1,c); } else if (ss[0]=='-') { int x1,y1; scanf("%d%d",&x1,&y1); Cut(x1,y1); scanf("%d%d",&x1,&y1); Link(x1,y1); } else if (ss[0]=='*') { int x,y,c; scanf("%d%d%d",&x,&y,&c); Split(x,y);cal(y,c,0); //printf("%d %d %d %d\n",x,y,s[x].d,s[x].c); } else { int x,y; scanf("%d%d",&x,&y); Split(x,y); //update(x);update(y); //printf("%d %d %d\n",x,s[x].son[0],s[x].son[1]); //printf("%d %d %d %d %d %d\n",x,s[x].c,y,s[y].c,s[y].son[0],s[y].son[1]); printf("%d\n",s[y].c); } } return 0;}
阅读全文
0 0
- 2631: tree LCT第二题
- 【BZOJ】2631 tree LCT入门题
- BZOJ 2631 tree LCT
- 【LCT】BZOJ 2631:tree
- 2631: tree LCT
- BZOJ 2631 Tree LCT
- BZOJ 2631 tree LCT
- 【BZOJ 2631】tree LCT
- BZOJ 2631: tree LCT
- bzoj 2631: tree LCT
- BZOJ 2631 Tree Link-Cut-Tree(LCT)
- BZOJ 2631(tree-LCT链上修改)
- bzoj 2631 tree LCT+标记处理
- bzoj 3282: Tree LCT第三题
- hdu 5002 Tree (LCT)
- HDU5002--Tree(LCT)
- bzoj2631: tree LCT
- LCT - hdu5002 Tree
- 深入浅出数据库索引原理
- Python笔记(一)——基础篇
- 程序中的配置文件
- JAVA基础之String类的介绍
- 杰卡德相似系数
- 2631: tree LCT第二题
- windows下在控制台下 mysql的一些简单的控制语句
- mysql备份还原,在win7系统上可以,在winservice2008中不能成功备份大数据。
- Coursera机器学习 Week7 笔记
- struts2之国际化(i18n)
- 全在其中
- 版本管理器的搭建
- 英语偏旁部首
- C++中的也能使用正则表达式