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. Ext4,Ext3的特点和区别

    Linux kernel 自 2.6.28 开始正式支持新的文件系统 Ext4. Ext4 是 Ext3 的改进版,修改了 Ext3 中部分重要的数据结构,而不仅仅像 Ext3 对 Ext2 那样,只 ...

  2. HD-ACM算法专攻系列(10)——大明A+B

    题目描述: 源码: 需要注意的一点是输出是最简形式,需要去除小数的后导0,而调用stripTrailingZeros()函数后,数会以科学计数法输出,所以需要调用toPlainString(). im ...

  3. 跨域调用接口——WebClient通过get和post请求api

    AJAX不可以实现跨域请求,经过特殊处理才行.一般后台可以通过WebClient实现跨域请求~ //get 请求        string url = string.Format("htt ...

  4. Core Java(一)

    一. 绪 1.软件:按照特定顺序组织的计算机数据和指令的集合. 软件开发:借助开发工具与计算机语言制作软件 2.计算机语言:用于人与计算机通讯的语言 分为机器语言,汇编语言,高级语言 高级语言分为编译 ...

  5. CSS3的常用属性(二)

    边框 边框圆角 border-radius: 100px 每个角可以设置两个值,x和y 补充: 可分别设置长,短半径,以“/”进行分隔,遵循顺时针的顺序,“/”之前为横轴半径,“/”之后为纵轴半径,如 ...

  6. 初识Git(二)

    与我们前一篇随笔一样创建文件夹,init我们创建的文件夹,并且创建一个test.txt文本文件,add文本文件,commit文本文件,接下来在文本文件中添加文本: 与上一次不同的是我们这一次在编辑文件 ...

  7. vector ----- size函数注意事项

    vector 的size函数返回vector大小,返回值类型为size_type,Member type size_type is an unsigned integral type,即无符号整数: ...

  8. 查看linux磁盘文件系统类型

    1.查看已经挂载了的磁盘的文件系统信息. [root@python2 ~]# df -hT 文件系统 类型 容量 已用 可用 已用% 挂载点 /dev/mapper/cl_python2-root x ...

  9. mysql日期加减运算

    MySQL 日期类型MySQL 日期类型:日期格式.所占存储空间.日期范围 比较. 日期类型        存储空间       日期格式                 日期范围 --------- ...

  10. 不要在.h文件中定义变量

    今天在头文件.h中初始化了一个数组和函数,在编译的时候提示这个数组和函数重新定义了,检查后发现,犯了一个致命的错误,在头文件中定义变量... 以下引用别人的一篇说明,警示自己. C语言作为一种结构化的 ...