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. Web前端错题模糊题记录

    title: Web前端错题模糊题记录 toc: true date: 2018-09-20 10:04:36 categories: Web tags: HTML CSS JavaScript HT ...

  2. 51nod 1021 石子归并 (动态规划 简单代码)

    题目: 思路:动态规划,递推式子 dp[i][j] = min(dp[i][j], dp[i][k] + dp[k+1][j] + sum[j] - sum[i-1]);     dp[i][j]表示 ...

  3. MyEclipse 启动之 java.lang.RuntimeException: No application id has been

    found. 今天公司刚买来一台服务器,配置安装 java 开发环境的时候,MyEclipse 无法启动,查看日志文件之后,具体错误信息 如下: [java] view plaincopyprint? ...

  4. error C2504: 未定义基类

    出错的情况为: type.h 文件中定义了一个结构体,但只给出了声明 namespace pcl { struct CSDDSignature; } 其定义在type.hpp文件中给出 namespa ...

  5. HDU 1394 Minimum Inversion Number【 树状数组 】

    题意:给出n个数,每次可以把第一个数挪到最后一个位置去,问这n种排列里面的最小逆序对数 先把最开始的逆序对数求出来 然后对于一个数a[i],比它小的数有a[i] - 1个,比它大的数有n - a[i] ...

  6. Optional是以enum和泛型为基础的高阶类型

    结论:1.optionals使用时需要检查:2.可以通过!+赋值语句转化为非optionals. Optional-Generic Enumeration enum Optional<T> ...

  7. 创建一个 Django 项目

    一. 创建项目 其中: 确认项目是否创建成功: 在 manage.py 目录上运行 python manage.py runserver server 启动后,在浏览器访问 http://127.0. ...

  8. 线段树(segment tree )

    http://www.cnblogs.com/TenosDoIt/p/3453089.html 写的非常好! 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少. 这让很 ...

  9. 史上最简单的在 Yii2.0 中将数据导出成 Excel

    在 vendor/yiisoft/yii2/helpers/ 创建一个 Excel.php <?php namespace yii\helpers;   class Excel{         ...

  10. 栈(stack)--c实现(使用双链表)

    是不是直接贴代码不太好,我竟然不知道说什么. 写这个考虑的问题,或者是纠结的问题是这个头指针怎么处理,也就是栈的顶部,最后采用的是初始化第一个栈空间浪费掉,栈顶是有元素的.好像应该去学习下画图,没图不 ...