BZOJ-2631 tree Link-Cut-Tree
2016-03-25 20:30
381 查看
2631: tree
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 3137 Solved: 1053
[Submit][Status][Discuss]
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
Source
题解:
非常好像到LCT,需要维护多个标记
正常的做4个操作:
1,split(u,v)后+c
2,cut(u1,v1),link(u2,v2)
3,split(u,v)后*c
4,split(u,v)后输出sum【u】
值得一提的是,int会炸,long long会T,需要unsigned int即可
自己遇到的问题:
此处先记录下标号,标号清零,再下传,不然会发生WA的情况
code:
Time Limit: 30 Sec Memory Limit: 128 MB
Submit: 3137 Solved: 1053
[Submit][Status][Discuss]
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
Source
题解:
非常好像到LCT,需要维护多个标记
正常的做4个操作:
1,split(u,v)后+c
2,cut(u1,v1),link(u2,v2)
3,split(u,v)后*c
4,split(u,v)后输出sum【u】
值得一提的是,int会炸,long long会T,需要unsigned int即可
自己遇到的问题:
此处先记录下标号,标号清零,再下传,不然会发生WA的情况
code:
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline int read() { int x=0,f=1; char ch=getchar(); while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();} while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} return x*f; } #define N 100010 #define p 51061 int fa ,son [2];unsigned int add ,mul ,size ,s ,val ,sum ; bool rev ;int n,q; inline void init(){for(int i=1; i<=n; i++)val[i]=sum[i]=mul[i]=size[i]=1;} inline bool is_root(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;} inline void rev1(int x){if (!x) return ;swap(son[x][0],son[x][1]);rev[x]^=1;} inline void delta(int x,int ad,int mu) { if (!x) return; val[x]=(val[x]*mu+ad)%p; sum[x]=(sum[x]*mu+ad*size[x])%p; add[x]=(add[x]*mu+ad)%p; mul[x]=(mul[x]*mu)%p; } void pb(int x) { if (rev[x]) rev1(son[x][0]),rev1(son[x][1]),rev[x]=0; int mu=mul[x],ad=add[x]; mul[x]=1,add[x]=0; if (mu!=1||ad!=0) delta(son[x][0],ad,mu),delta(son[x][1],ad,mu); } void update(int x) { size[x]=(size[son[x][0]]+size[son[x][1]]+1)%p; sum[x]=(sum[son[x][0]]+sum[son[x][1]]+val[x])%p; } inline void rotate(int x) { int y=fa[x],w=son[y][1]==x;son[y][w]=son[x][w^1]; if (son[x][w^1]) fa[son[x][w^1]]=y; if (fa[y]) { int z=fa[y];if (son[z][0]==y) son[z][0]=x; else if (son[z][1]==y) son[z][1]=x; } fa[x]=fa[y]; fa[y]=x; son[x][w^1]=y; update(y); } inline void splay(int x) { int top=1,i=x,y; s[1]=i; while (!is_root(i)) s[++top]=i=fa[i]; while (top) pb(s[top--]); while (!is_root(x)) { y=fa[x]; if (!is_root(y)) if ((son[fa[y]][0]==y)^(son[y][0]==x)) rotate(x);else rotate(y); rotate(x); } update(x); } inline void access(int x){for (int y=0; x; y=x,x=fa[x])splay(x),son[x][1]=y,update(x);} inline void makeroot(int x){access(x),splay(x),rev1(x);} inline void link(int x,int y){makeroot(x); fa[x]=y;access(x);} inline void cutf(int x){access(x),splay(x);fa[son[x][0]]=0; son[x][0]=0;update(x);} inline void cut(int x,int y){makeroot(x); cutf(y);} void split(int x,int y){makeroot(y);access(x);splay(x);} //Link-Cut-Tree int main() { n=read(),q=read(); init(); for (int u,v,i=1; i<=n-1; i++) u=read(),v=read(),link(u,v); for (int i=1; i<=q; i++) { char opt[10];scanf("%s",opt); int u,v,c,u1,u2,v1,v2; switch (opt[0]) { case '+': u=read(),v=read(),c=read(); split(u,v); delta(u,c,1); break; case '-': u1=read(),v1=read(),u2=read(),v2=read(); cut(u1,v1); link(u2,v2);break; case '*': u=read(),v=read(),c=read(); split(u,v); delta(u,0,c); break; case '/': u=read(),v=read(); split(u,v); printf("%d\n",sum[u]); break; } } // for (int i=1; i<=n; i++) // printf("%d %d %d %d\n",val[i],sum[i],add[i],mul[i]); return 0; }
相关文章推荐
- ssm 属性外键关联的属性
- IOS开发for循环创建button
- VB感受
- 第四周自我总结
- Android 使用WebView
- Android之ActivityManagerService浅谈
- Java多线程程序设计详细解析
- Android 源码系列之<一>从源码的角度深入理解ImageView的ScaleType属性
- Auto Mapper04(MVC中的配置)
- 3-2 安装命令
- Spring IoC — 基于XML的配置
- 自己实现一个Python调试器
- 安装oracle的步骤
- 【CV】ICCV2015_Describing Videos by Exploiting Temporal Structure
- Iterator中hasNext(), next() 和ResultSet结果集的next方法的区别
- 决策树和随机决策森林基本原理和应用实例
- 最近研究了一下C++里面的const
- 四种XML解析方式详解
- 十进制数转换为八进制数/十六进制数
- 局部更新listview的问题(只更新某个item)