BZOJ_2631_tree_LCT

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


LCT模板题。注意乘法和加法下传的顺序。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 100050
#define mod 51061
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
typedef unsigned int ui;
int n,m,ch[N][2],f[N],rev[N];
ui sum[N],mul[N],add[N],siz[N],val[N];
char opt[10];
inline bool isrt(int x) {
return ch[f[x]][0]!=x&&ch[f[x]][1]!=x;
}
void pushdown(int p) {
if(mul[p]!=1) {
ui u=mul[p];
sum[ls]=sum[ls]*u%mod; mul[ls]=mul[ls]*u%mod; add[ls]=add[ls]*u%mod; val[ls]=val[ls]*u%mod;
sum[rs]=sum[rs]*u%mod; mul[rs]=mul[rs]*u%mod; add[rs]=add[rs]*u%mod; val[rs]=val[rs]*u%mod;
mul[p]=1;
}
if(add[p]) {
ui d=add[p];
sum[ls]=(sum[ls]+siz[ls]*d%mod)%mod; add[ls]=(add[ls]+d)%mod; val[ls]=(val[ls]+d)%mod;
sum[rs]=(sum[rs]+siz[rs]*d%mod)%mod; add[rs]=(add[rs]+d)%mod; val[rs]=(val[rs]+d)%mod;
add[p]=0;
}
if(rev[p]) {
swap(ch[ls][0],ch[ls][1]);
swap(ch[rs][0],ch[rs][1]);
rev[ls]^=1; rev[rs]^=1;
rev[p]=0;
}
/*cal(ls , add[p] , mul[p] , rev[p]);
cal(rs , add[p] , mul[p] , rev[p]);
add[p] = rev[p] = 0 , mul[p] = 1;*/
}
void pushup(int p) {
siz[p]=siz[ls]+siz[rs]+1;
sum[p]=(sum[ls]+sum[rs]+val[p])%mod;
}
void update(int p) {
if(!isrt(p)) update(f[p]);
pushdown(p);
}
void rotate(int x) {
int y=f[x],z=f[y],k=get(x);
if(!isrt(y)) ch[z][ch[z][1]==y]=x;
ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
ch[x][!k]=y; f[y]=x; f[x]=z;
pushup(y); pushup(x);
}
void splay(int x) {
update(x);
for(int fa;fa=f[x],!isrt(x);rotate(x))
if(!isrt(fa))
rotate(get(fa)==get(x)?fa:x);
}
void access(int p) {
int t=0;
while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
}
void makeroot(int p) {
access(p); splay(p); swap(ls,rs); rev[p]^=1;
}
void link(int x,int p) {
makeroot(x); f[x]=p;
}
void cut(int x,int p) {
makeroot(x); access(p); splay(p); ls=f[x]=0;
}
void split(int x,int p) {
makeroot(x); access(p); splay(p);
}
int main() {
scanf("%d%d",&n,&m);
int i,x,y,z,w;
for(i=1;i<=n;i++) val[i]=mul[i]=siz[i]=sum[i]=1;
for(i=1;i<n;i++) {
scanf("%d%d",&x,&y); link(x,y);
}
for(i=1;i<=m;i++) {
scanf("%s%d%d",opt,&x,&y);
int p=y;
if(opt[0]=='+') {
scanf("%d",&z); split(x,p);
sum[p]=(sum[p]+siz[p]*z%mod)%mod;
val[p]=(val[p]+z)%mod;
add[p]=(add[p]+z)%mod;
//cal(p,z,1,0);
}else if(opt[0]=='-') {
scanf("%d%d",&z,&w); cut(x,y); link(z,w);
}else if(opt[0]=='*') {
scanf("%d",&z); split(x,p);
sum[p]=sum[p]*z%mod;
val[p]=val[p]*z%mod;
add[p]=add[p]*z%mod;
mul[p]=mul[p]*z%mod;
//cal(p,0,z,0);
}else {
split(x,p); printf("%u\n",sum[p]);
}
}
}

BZOJ_2631_tree_LCT的更多相关文章

随机推荐

  1. scrollWidth,clientWidth与offsetWidth的区别

    scrollWidth  是对象的实际内容的宽,不包边线宽度,会随对象中内容的多少改变(内容多了可能会改变对象的实际宽度). clientWidth  是对象可见的宽度,不包滚动条等边线,会随窗口的显 ...

  2. 爬虫Scrapy框架运用----房天下二手房数据采集

    在许多电商和互联网金融的公司为了更好地服务用户,他们需要爬虫工程师对用户的行为数据进行搜集.分析和整合,为人们的行为选择提供更多的参考依据,去服务于人们的行为方式,甚至影响人们的生活方式.我们的scr ...

  3. 经典的java中return和finally问题!

    经典的java中return和finally问题! 标签: 杂谈 分类: java学习 前一段时间 参加公司的笔试问了这个问题,回来一查才知道当时自己做错了,百思不得其解,上网查到下面的程序,但是运行 ...

  4. c语言,文件操作总结

    C语言文件操作 一.标准文件的读写 1.文件的打开 fopen() 文件的打开操作表示将给用户指定的文件在内存分配一个FILE结构区,并将该结构的指针返回给用户程序,以后用户程序就可用此FILE指针来 ...

  5. 10.API 接口自动化测试的基本原理

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 28.0px Helvetica } p.p2 { margin: 0.0px 0.0px 0.0px 0. ...

  6. Django开发环境静态文件访问配置

    settings主要配置项目: STATIC_ROOT = 'D:\Dev\jpDev\czxg\assets' #这个地方是所在系统标准目录文法配置 STATIC_URL = '/static/' ...

  7. STL源码标注_空间适配器

    /* stl_alloc.h */ SGI STL空间适配器的主要由alloc.h和stl_alloc.h实现 SGI STL空间适配器的核心: 第一级适配器__malloc_alloc_templa ...

  8. 手把手教你全家桶之React(二)

    前言 上一篇已经讲了一些react的基本配置,本遍接着讲热更新以及react+redux的配置与使用. 热更新 我们在实际开发时,都有用到热更新,在修改代码后,不用每次都重启服务,而是自动更新.并而不 ...

  9. Spark学习笔记

    Map-Reduce 我认为上图代表着MapReduce不仅仅包括Map和Reduce两个步骤这么简单,还有两个隐含步骤没有明确,全部步骤包括:切片.转换.聚合.叠加,按照实际的运算场景上述步骤可以简 ...

  10. 微信小程序之获取用户位置权限(拒绝后提醒)

    微信小程序获取用户当前位置有三个方式: 1. wx.getLocation(多与wx.openLocation一起用) 获取当前的精度.纬度.速度.不需要授权.当type设置为gcj02 返回可用于w ...