Code:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std; void setIO(string a)
{
freopen((a+".in").c_str(),"r",stdin);
freopen((a+".out").c_str(),"w",stdout);
} #define maxn 100009
#define ll long long
#define mod 51061 int f[maxn], ch[maxn][2],siz[maxn],tag[maxn],sta[maxn],n,m;
ll mult[maxn], add[maxn], sumv[maxn], val[maxn]; int lson(int x)
{
return ch[x][0];
}
int rson(int x)
{
return ch[x][1];
}
int get(int x)
{
return ch[f[x]][1]==x;
}
int isRoot(int x)
{
return !(ch[f[x]][1]==x||ch[f[x]][0]==x);
}
void mark(int x)
{
if(!x)return;
swap(ch[x][0], ch[x][1]), tag[x]^=1;
} void pushdown(int x){
// if(!x)return;
if(mult[x]!=1)
{
if(lson(x))
{
sumv[lson(x)]*=mult[x];
mult[lson(x)]*=mult[x];
add[lson(x)]*=mult[x];
val[lson(x)]*=mult[x]; add[lson(x)]%=mod;
mult[lson(x)]%=mod;
sumv[lson(x)]%=mod;
val[lson(x)]%=mod;
}
if(rson(x))
{
sumv[rson(x)]*=mult[x];
mult[rson(x)]*=mult[x];
add[rson(x)]*=mult[x];
val[rson(x)]*=mult[x]; add[rson(x)]%=mod;
mult[rson(x)]%=mod;
sumv[rson(x)]%=mod;
val[rson(x)]%=mod;
}
mult[x]=1;
}
if(add[x])
{
if(lson(x))
{
sumv[lson(x)]+=add[x]*siz[lson(x)];
add[lson(x)]+=add[x];
val[lson(x)]+=add[x]; add[lson(x)]%=mod;
sumv[lson(x)]%=mod;
val[lson(x)]%=mod;
}
if(rson(x))
{
sumv[rson(x)]+=add[x]*siz[rson(x)];
add[rson(x)]+=add[x];
val[rson(x)]+=add[x]; add[rson(x)]%=mod;
sumv[rson(x)]%=mod;
val[rson(x)]%=mod;
}
add[x]=0;
}
if(tag[x]) mark(ch[x][0]), mark(ch[x][1]), tag[x]=0;
} void pushup(int x)
{
if(!x)return;
siz[x]=siz[lson(x)]+siz[rson(x)]+1;
sumv[x]=(sumv[lson(x)]+sumv[rson(x)]+val[x])%mod;
} void rotate(int o){
int old=f[o],fold=f[old],which=get(o);
if(!isRoot(old)) ch[fold][ch[fold][1]==old]=o;
f[o]=fold;
ch[old][which]=ch[o][which^1], f[ch[old][which]]=old;
ch[o][which^1]=old,f[old]=o;
pushup(old),pushup(o),pushup(fold);
}
void splay(int x){
int v=0,u=x;
sta[++v]=u;
while(!isRoot(u)) sta[++v]=f[u],u=f[u];
while(v) pushdown(sta[v--]);
u=f[u];
for(int fa;(fa=f[x])!=u;rotate(x))
if(f[fa]!=u) rotate(get(x)==get(fa)?fa:x);
}
void Access(int x)
{
for(int y=0;x;y=x,x=f[x]) splay(x), ch[x][1]=y, pushup(x);
}
void makeRoot(int x)
{
Access(x), splay(x),mark(x);
}
void split(int x,int y)
{
makeRoot(x), Access(y), splay(y);
}
void Link(int x,int y)
{
makeRoot(x), f[x]=y;
}
void cut(int x,int y)
{
makeRoot(x), Access(y), splay(y);
f[x] = ch[y][0] = 0, pushup(y);
} void debug(){ for(int i=1;i<=n;++i) printf("%d %lld\n",siz[i],sumv[i]); } int main(){
//setIO("input");
memset(add,0,sizeof(add)), memset(mult,1,sizeof(mult));
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) sumv[i]=val[i]=1;
for(int i=1;i<n;++i)
{
int a,b;
scanf("%d%d",&a,&b);
Link(a,b);
} for(int i=1;i<=m;++i)
{
char opt[10];
int a,b,c,d;
scanf("%s",opt);
if(opt[0]=='+')
{
scanf("%d%d%d",&a,&b,&c);
split(a,b);
sumv[b]+=siz[b]*c;
add[b]+=c;
val[b]+=c; sumv[b]%=mod;
add[b]%=mod;
val[b]%=mod;
}
if(opt[0]=='-')
{
scanf("%d%d%d%d",&a,&b,&c,&d);
cut(a,b);
Link(c,d);
}
if(opt[0]=='*')
{
scanf("%d%d%d",&a,&b,&c);
split(a,b);
sumv[b]*=c;
add[b]*=c;
mult[b]*=c;
val[b]*=c; sumv[b]%=mod;
add[b]%=mod;
mult[b]%=mod;
val[b]%=mod;
}
if(opt[0]=='/')
{
scanf("%d%d",&a,&b);
split(a,b);
printf("%lld\n",sumv[b]%mod);
}
}
return 0;
}

  

洛谷 P1501 [国家集训队]Tree II Link-Cut-Tree的更多相关文章

  1. 洛谷 P1501 [国家集训队]Tree II 解题报告

    P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...

  2. 洛谷P1501 [国家集训队]Tree II(LCT,Splay)

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  3. 【刷题】洛谷 P1501 [国家集训队]Tree II

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  4. 洛谷P1501 [国家集训队]Tree II(LCT)

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  5. 洛谷P1501 [国家集训队]Tree II(打标记lct)

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  6. [洛谷P1501][国家集训队]Tree II

    题目大意:给一棵树,有四种操作: $+\;u\;v\;c:$将路径$u->v$区间加$c$ $-\;u_1\;v_1\;u_2\;v_2:$将边$u_1-v_1$切断,改成边$u_2-v_2$, ...

  7. 洛谷 P1501 [国家集训队]Tree II

    看来这个LCT板子并没有什么问题 #include<cstdio> #include<algorithm> using namespace std; typedef long ...

  8. [洛谷P1501] [国家集训队]Tree II(LCT模板)

    传送门 这是一道LCT的板子题,说白了就是在LCT上支持线段树2的操作. 所以我只是来存一个板子,并不会讲什么(再说我也不会,只能误人子弟2333). 不过代码里的注释可以参考一下. Code #in ...

  9. 【洛谷 P3690】 【模板】Link Cut Tree (动态树)

    题目链接 \(RT\). FlashHu巨佬的博客 #include <cstdio> #define R register int #define I inline void #defi ...

随机推荐

  1. iOS对象方法和类方法的区别与调用方式

    作为一个iOS程序员初学者,会搞不清楚对象方法和类方法的区别 -(void)duixiangfangfa ; +(void)leifangfa; - 代表实例方法,它在类的一个具体实例范围内执行,也就 ...

  2. xmanager使用

    Xmanager全称Netsarang Xmanager,是国外一套非常优秀的远程监控软件.在UNIX/Linux和Windows网络环境中,Xmanager是最好的连通解决方案.我推 荐大家下载En ...

  3. ubuntu下创建文件夹快捷方式

    title: ubuntu下创建文件夹快捷方式 toc: false date: 2018-09-01 17:22:28 categories: methods tags: ubuntu 快捷方式 s ...

  4. vue keep-alive保存路由状态1 (接下篇)

    本文很长,但是很详细,请耐心看完就一目了然了有下篇 keep-alive 是 Vue 内置的一个组件,使被包含的组件保留状态,或避免重新渲染. 1. 基础用法,缓存所有路由: <keep-ali ...

  5. xshell同时发送多条命令

    1.如图,勾选撰写栏 勾选全部会话 下面的是一个很方便的小技巧.分屏 如下图垂直排列 水平排列等等

  6. mysql索引的注意事项

    索引的优点 大大加快数据的查询速度 使用分组和排序进行数据查询时,可以显著减少查询时分组和排序的时间 创建唯一索引,能够保证数据库表中每一行数据的唯一性 在实现数据的参考完整性方面,可以加速表和表之间 ...

  7. Xshell调整终端显示的最大行数(缓冲区)

    1 选择会话,按顺序点击文件->属性 ,打开"会话属性"窗口 如下 在"会话属性"窗口中选择“终端” 修改缓冲区大小的值:其范围为0~2147483647 ...

  8. javascipt入门

    一.javascript简介 javascript:(基于对象的编程语言:内部很多对象,我们只需要使用即可,几乎不需要自己创建对象) ECMAScript DOM BOM 存放位置: 建议代码放到ht ...

  9. Swift 4.0:访问级别(访问控制)

    基础篇 注: 下文中所提及的类和类型为Class, Enum和Struct Swift中的访问级别有以下五种: open: 公开权限, 最高的权限, 可以被其他模块访问, 继承及复写. public: ...

  10. CDR X6三折促销活动,可入

    继CDR X6双十二限量活动之后,CorelDRAW官方为庆祝2018新年新气象,折扣狂潮,又来一波.上次活动由于时间短,任务急,数量少,使得不少小伙伴抱憾而止,选择默默等待良机.现在,良机来了,即便 ...