题目描述

一棵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的余数。

输入输出格式

输入格式:

 

第一行两个整数n,q

接下来n-1行每行两个正整数u,v,描述这棵树

接下来q行,每行描述一个操作

 

输出格式:

 

对于每个/对应的答案输出一行

 

输入输出样例

输入样例#1: 复制

3 2
1 2
2 3
* 1 3 4
/ 1 1
输出样例#1: 复制

4

说明

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

By (伍一鸣)

题解:这题其实没有什么很难的地方,主要考点就是lct的打标记(还是两个orz),显然链修改跟线段树的打标记是一样的

就是酱紫了~

结果%=写成%调了一个晚上2333

代码如下

#include<map>
#include<set>
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100010
#define mod 51061
#define lson ch[x][0]
#define rson ch[x][1]
#define int long long
using namespace std; int tag1[N],tag2[N],tag3[N],sum[N],sz[N],f[N],ch[N][],w[N]; int not_root(int now)
{
int x=f[now];
return lson==now||rson==now;
} int push_up(int x)
{
sum[x]=(sum[lson]+sum[rson]+w[x])%mod;
sz[x]=sz[lson]+sz[rson]+;
} int rev(int x)
{
swap(lson,rson);
tag1[x]^=;
} int add(int x,int cost)
{
sum[x]+=cost*sz[x];
sum[x]%=mod;
w[x]+=cost;
w[x]%=mod;
tag2[x]+=cost;
tag2[x]%=mod;
} int mul(int x,int cost)
{
sum[x]*=cost;
sum[x]%=mod;
w[x]*=cost;
w[x]%=mod;
tag3[x]*=cost;
tag3[x]%=mod;
tag2[x]*=cost;
tag2[x]%=mod;
} int push_down(int x)
{
if(tag3[x]!=)
{
mul(lson,tag3[x]);
mul(rson,tag3[x]);
tag3[x]=;
}
if(tag2[x])
{
add(lson,tag2[x]);
add(rson,tag2[x]);
tag2[x]=;
}
if(tag1[x])
{
rev(lson);
rev(rson);
tag1[x]=;
}
} int rotate(int x)
{
int y=f[x],z=f[y],kd=ch[y][]==x,xs=ch[x][!kd];
if(not_root(y))
{
ch[z][ch[z][]==y]=x;
}
ch[x][!kd]=y;
ch[y][kd]=xs;
if(xs) f[xs]=y;
f[y]=x;
f[x]=z;
push_up(y);
} int push_all(int x)
{
if(not_root(x))
{
push_all(f[x]);
}
push_down(x);
} int splay(int x)
{
int y,z;
push_all(x);
while(not_root(x))
{
y=f[x],z=f[y];
if(not_root(y))
{
(ch[y][]==x)^(ch[z][]==y)?rotate(x):rotate(y);
}
rotate(x);
}
push_up(x);
} int access(int x)
{
for(int y=; x; y=x,x=f[x])
{
splay(x);
rson=y;
push_up(x);
}
} int make_root(int x)
{
access(x);
splay(x);
rev(x);
} int split(int x,int y)
{
make_root(x);
access(y);
splay(y);
} int link(int x,int y)
{
make_root(x);
f[x]=y;
} int cut(int x,int y)
{
split(x,y);
f[x]=ch[y][]=;
} char s[];
int n,m; signed main()
{
scanf("%lld %lld",&n,&m);
for(int i=; i<=n; i++)
{
sum[i]=w[i]=tag3[i]=sz[i]=;
}
for(int i=; i<n; i++)
{
int from,to;
scanf("%lld %lld",&from,&to);
link(from,to);
}
for(int i=; i<=m; i++)
{
scanf("%s",s);
if(s[]=='*')
{
int x,y,cost;
scanf("%lld %lld %lld",&x,&y,&cost);
split(y,x);
mul(x,cost);
}
if(s[]=='-')
{
int u1,v1,u2,v2;
scanf("%lld %lld %lld %lld",&u1,&v1,&u2,&v2);
cut(u1,v1);
link(u2,v2);
}
if(s[]=='+')
{
int x,y,cost;
scanf("%lld %lld %lld",&x,&y,&cost);
split(y,x);
add(x,cost);
}
if(s[]=='/')
{
int u,v;
scanf("%lld %lld",&u,&v);
split(u,v);
printf("%lld\n",sum[v]);
}
}
}

洛谷P1501 [国家集训队]Tree II(打标记lct)的更多相关文章

  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

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

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

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

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

    Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...

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

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

  9. 洛谷.1501.[国家集训队]Tree II(LCT)

    题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...

随机推荐

  1. Storm开发——环境配置部署

    配置开发环境:http://storm.apache.org/releases/current/Setting-up-development-environment.html 开发环境定义: Stor ...

  2. apache DOCUMENT_ROOT

    问题描述:本地页面错误,+1上正常 本地及+1apache配置 <VirtualHost *:> ServerAdmin webmaster@dummy-host.example.com ...

  3. 高效率terminal和sublime 相互启动

    在日常的工作中,我们经常使用到terminal和Sublime .今天给大家介绍下怎样高效率的实现terminal和sublime 相互启动 (这里说的是MAC环境,我用的是Sublime Text ...

  4. npm上传包

    npm上传包 向npm上传一个包是很容易的,只需要三步: 1.在npm官网注册一个账户,然后在cmd中登录账户 注:npm不要使用代理,直接连接 https://registry.npms.org/. ...

  5. 上传项目到git

    …or create a new repository on the command line   echo "# test" >> README.md git ini ...

  6. Oracle11gR2--手工建库&dbca建库

    1 Oracle11gR2 dbca建库 [oracle@localhost ~]$ cd $ORACLE_BASE/database [oracle@localhost database]$ dbc ...

  7. Zabbix 监控页面中文乱码

    问题描述: 如题,我相信大多数人都遇到过这个问题,Zabbix 监控图 中文乱码. 解决这个问题也很简单:( Zabbix 网页目录中缺少字体 ) 1.打开 Windows 的 C:\Windows\ ...

  8. firebug,chrome调试工具的使用

    ​http://ued.taobao.org/blog/?p=5534 chrome调试 http://www.cnblogs.com/QLeelulu/archive/2011/08/28/2156 ...

  9. 用vim生成一批递增ID

    假设说要生成1000个以xxx开头的后面加数字的ID,比如xxx1到xxx1000.一般我们可以通过.csv去递增,然后替换,但是直接用vim也是可以达到这样的目的. 下面通过一个gif图演示这个过程 ...

  10. kubernetes role

    https://kubernetes.io/docs/admin/authorization/rbac/