bzoj2631 tree
来源:互联网 发布:dd linux sync 编辑:程序博客网 时间:2024/05/22 10: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行,每行描述一个操作 Output
对于每个/对应的答案输出一行
对于维护的操作可以参见【bzoj1798】。之后就是套上一个LCT,用splay维护。
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int p=51061;int rd(){ int x=0; char c=getchar(); while (c<'0'||c>'9') c=getchar(); while (c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); } return x;}char rdc(){ char c=getchar(); while (c!='+'&&c!='-'&&c!='*'&&c!='/') c=getchar(); return c;}int fa[100010],son[100010][2],sta[100010],size[100010],inv[100010],n,q;unsigned int plus[100010],multi[100010],sum[100010],w[100010];int isroot(int u){ return son[fa[u]][0]!=u&&son[fa[u]][1]!=u;}void down(int u){ int v; /*size[u]=1; if (v=son[u][0]) size[u]+=size[v]; if (v=son[u][1]) size[u]+=size[v];*/ if (inv[u]) { if (v=son[u][0]) inv[v]^=1; if (v=son[u][1]) inv[v]^=1; swap(son[u][0],son[u][1]); inv[u]=0; } if (multi[u]!=1) { sum[u]=sum[u]*multi[u]%p; w[u]=w[u]*multi[u]%p; if (v=son[u][0]) { multi[v]=multi[v]*multi[u]%p; plus[v]=plus[v]*multi[u]%p; } if (v=son[u][1]) { multi[v]=multi[v]*multi[u]%p; plus[v]=plus[v]*multi[u]%p; } multi[u]=1; } if (plus[u]) { sum[u]=(sum[u]+size[u]*plus[u]%p)%p; w[u]=(w[u]+plus[u])%p; if (v=son[u][0]) plus[v]=(plus[v]+plus[u])%p; if (v=son[u][1]) plus[v]=(plus[v]+plus[u])%p; plus[u]=0; }}void up(int u){ size[u]=1; if (son[u][0]) size[u]+=size[son[u][0]]; if (son[u][1]) size[u]+=size[son[u][1]]; sum[u]=w[u]; if (son[u][0]) { down(son[u][0]); sum[u]+=sum[son[u][0]]; } if (son[u][1]) { down(son[u][1]); sum[u]+=sum[son[u][1]]; } sum[u]%=p;}void rot(int u,int k){ int v=son[u][k],w=son[v][k^1],p=fa[u]; if (!isroot(u)) son[p][son[p][1]==u]=v; fa[v]=p; son[v][k^1]=u; fa[u]=v; son[u][k]=w; fa[w]=u; up(u); up(v); up(p);}void splay(int u){ int top=0,x,y,v,w; for (int i=u;;i=fa[i]) { sta[++top]=i; if (isroot(i)) break; } for (;top;top--) down(sta[top]); while (!isroot(u)) { v=fa[u]; x=son[v][1]==u; if (isroot(v)) rot(v,x); else { w=fa[v]; y=son[w][1]==v; if (x==y) { rot(w,y); rot(v,x); } else { rot(v,x); rot(w,y); } } }}void access(int u){ int t=u,v=0; while (u) { splay(u); son[u][1]=v; up(u); v=u; u=fa[u]; } splay(t);}void makeroot(int u){ access(u); inv[u]^=1;}void link(int u,int v){ makeroot(u); fa[u]=v;}void cut(int u,int v){ makeroot(u); access(v); son[v][0]=fa[u]=0; up(v);}void modip(int u,int v,unsigned int x){ makeroot(u); access(v); plus[v]=(plus[v]+x)%p;}void modim(int u,int v,unsigned int x){ makeroot(u); access(v); multi[v]=multi[v]*x%p; plus[v]=plus[v]*x%p;}int qry(int u,int v){ makeroot(u); access(v); down(v); return sum[v];}int main(){ char c; int u,v,x,y; n=rd(); q=rd(); for (int i=1;i<=n;i++) multi[i]=sum[i]=size[i]=w[i]=1; for (int i=1;i<n;i++) { u=rd(); v=rd(); link(u,v); } while (q--) { c=rdc(); u=rd(); v=rd(); switch (c) { case '+': x=rd(); modip(u,v,x); break; case '-': x=rd(); y=rd(); cut(u,v); link(x,y); break; case '*': x=rd(); modim(u,v,x); break; case '/': printf("%d\n",qry(u,v)); break; } }}
0 0
- bzoj2631 tree
- bzoj2631: tree
- 【BZOJ2631】tree
- bzoj2631 tree
- [BZOJ2631] tree
- [BZOJ2631]tree
- BZOJ2631: tree
- bzoj2631: tree
- Bzoj2631 Tree
- bzoj2631 tree
- BZOJ2631: tree
- 【bzoj2631】tree
- bzoj2631 tree
- 【bzoj2631】tree
- 【BZOJ2631】tree
- bzoj2631: tree
- bzoj2631 tree(伍一鸣)
- bzoj2631: tree LCT
- hive系列(2)---自定义函数UDF
- java分支结构
- Java夯实基础(Android注解全解析)
- JDBC批量插入与更新
- Bootstrap 排版样式
- bzoj2631 tree
- Unity零散笔记
- 排序算法:冒泡排序
- hive系列(3)---Transform
- 设计模式--观察者模式(详解)
- DHCP
- asp.net 后台代码改变a标签的内容文字和链接href
- Ext常用组件
- 在树莓派上用Python Rpi.GPIO调试液晶模块