【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2631

【题目大意】

  要求支持链修改,链查询,边断开,连接操作

【题解】

  链修改分乘和加split之后在LCT上打tag,断开和连接LCT基础操作即可。

【代码】

#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef long long LL;
const LL mod=51061;
const int N=100010;
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;
}
namespace Link_Cut_Tree{
int f[N],son[N][2],tmp[N],size[N]; bool rev[N];
LL val[N],sum[N],at[N],mt[N];
void Initialize(){
memset(f,0,sizeof(f));
memset(son,0,sizeof(son));
memset(val,0,sizeof(val));
memset(rev,0,sizeof(rev));
memset(sum,0,sizeof(sum));
memset(at,0,sizeof(at));
memset(mt,0,sizeof(mt));
}
void modify(int x,int m,int a){
if(!x)return;
val[x]=(val[x]*m+a)%mod;
sum[x]=(sum[x]*m+a*size[x])%mod;
at[x]=(at[x]*m+a)%mod;
mt[x]=(mt[x]*m)%mod;
}
bool isroot(int x){return !f[x]||son[f[x]][0]!=x&&son[f[x]][1]!=x;}
void rev1(int x){if(!x)return;swap(son[x][0],son[x][1]);rev[x]^=1;}
void pb(int x){
if(rev[x])rev1(son[x][0]),rev1(son[x][1]),rev[x]=0;
int m=mt[x],a=at[x];
mt[x]=1; at[x]=0;
if(m!=1||a!=0){modify(son[x][0],m,a);modify(son[x][1],m,a);}
}
void up(int x){
sum[x]=(val[x]+sum[son[x][0]]+sum[son[x][1]])%mod;
size[x]=(size[son[x][0]]+size[son[x][1]]+1)%mod;
}
void rotate(int x){
int y=f[x],w=son[y][1]==x;
son[y][w]=son[x][w^1];
if(son[x][w^1])f[son[x][w^1]]=y;
if(f[y]){
int z=f[y];
if(son[z][0]==y)son[z][0]=x;else if(son[z][1]==y)son[z][1]=x;
}f[x]=f[y];f[y]=x;son[x][w^1]=y;up(y);
}
void splay(int x){
int s=1,i=x,y;tmp[1]=i;
while(!isroot(i))tmp[++s]=i=f[i];
while(s)pb(tmp[s--]);
while(!isroot(x)){
y=f[x];
if(!isroot(y)){if((son[f[y]][0]==y)^(son[y][0]==x))rotate(x);else rotate(y);}
rotate(x);
}up(x);
}
void access(int x){for(int y=0;x;y=x,x=f[x])splay(x),son[x][1]=y,up(x);}
// 查询x所在的树的根
int root(int x){access(x);splay(x);while(son[x][0])x=son[x][0];return x;}
// 使x成为根
void makeroot(int x){access(x);splay(x);rev1(x);}
// 将x和y所属树合并
void link(int x,int y){makeroot(x);f[x]=y;access(x);}
// 将x和其父节点分开
void cutf(int x){access(x);splay(x);f[son[x][0]]=0;son[x][0]=0;up(x);}
// 将边x-y切断
void cut(int x,int y){makeroot(x);cutf(y);}
// 提取链
void split(int x,int y){makeroot(y);access(x);splay(x);}
// 查询x到y的链和
int ask(int x,int y){split(x,y);return sum[x];}
// 查询节点到根的距离
int query(int x){access(x);splay(x);return sum[x];}
// 将x为下标的值改为y
int change(int x,int y){makeroot(x);val[x]=y;up(x);}
// 将x的父亲改为y
int changef(int x,int y){cutf(x);f[x]=y;}
// 链上点权加法
void add(int x,int y,int z){split(x,y);modify(x,1,z);}
// 链上点权乘法
void mul(int x,int y,int z){split(x,y);modify(x,z,0);}
}
int n,m;
int main(){
n=read(); m=read();
using namespace Link_Cut_Tree;
Initialize();
for(int i=1;i<=n;i++)val[i]=sum[i]=mt[i]=size[i]=1;
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
link(x,y);
}char op[5];
while(m--){
scanf("%s",op);
int x,y,z;
if(op[0]=='+'){x=read();y=read();z=read();add(x,y,z);}
if(op[0]=='-'){
x=read();y=read();cut(x,y);
x=read();y=read();link(x,y);
}
if(op[0]=='*'){x=read();y=read();z=read();mul(x,y,z);}
if(op[0]=='/'){x=read();y=read();printf("%d\n",ask(x,y));}
}return 0;
}

最新文章

  1. 安装zookeeper
  2. MySQL数据库
  3. 通过python将图片生成字符画
  4. [转]Spring 注解总结
  5. hdu Cup
  6. Java中double类型的数据精确到小数点后两位
  7. 关于css中透明度继承的问题
  8. div中实现居中
  9. RTP/RTCP/RTSP/RSVP/SDP
  10. ROS Node/Topic/Message/Service的一些问题
  11. pscs6
  12. 一步一步学Vue(三)
  13. mysql服务处理流程
  14. 深入探讨List&lt;&gt;中的一个姿势。
  15. php面试上机题(2018-3-3)
  16. 【Eclipse】-NO.163.Eclipse.1 -【Eclipse springboot 1.x 创建maven工程初始化报错】
  17. python 取值方法:截取字符串
  18. 【转】python文件和目录操作方法大全(含实例)
  19. Verilog中的阻塞与非阻塞
  20. CentOS 7的安装

热门文章

  1. 深入浅出MyBatis:JDBC和MyBatis介绍
  2. MongoDB 数据库(2)
  3. MSSQL 视图/事务(TRAN[SACTION])/存储过程(PROC[EDURE])/触发器(TRIGGER )
  4. Android控件——AutoCompleteTextView与MultiAutoCompleteTextView(实现自动匹配输入的内容)
  5. Java开源爬虫框架crawler4j
  6. css position的值
  7. 【Python学习笔记】有关包的基本知识
  8. 虚拟机出现intel vt -x 处于禁用状态打不开处理方式
  9. ktime使用例子【原创】
  10. linux 下多版本gcc 共存问题