洛谷P1501 [国家集训队]Tree II(LCT,Splay)
关于LCT的其它问题可以参考一下我的LCT总结
一道LCT很好的练习放懒标记技巧的题目。
一开始看到又做加法又做乘法的时候我是有点mengbi的。
然后我想起了模板线段树2。。。。。。(相信各位Dalao一定做过这道题)
这里的维护懒标记方法很像。除了翻转标记以外还要维护乘法标记和加法标记。
根据运算优先级,乘法是要先算的,所以先放,放的时候子树的\(sum\),乘法标记,加法标记,儿子的\(val\)统统都要乘一遍。
放加法标记的时候,想到线段树的区间大小是稳定的,而Splay并不是,所以还要维护\(size\),于是子树的\(sum\)要加上子树的\(size\)再乘上标记,而儿子的\(val\)和加法标记直接加上该标记的值。
再注意一个小细节。
有没有觉得51061这个数好小啊。。。我看到的时候特高兴,不用担心longlong的问题了。然而。。。
\(51061^2=2607225721>2147483647\)
所以要开unsigned int。。。。。。
还是上代码吧
#include<cstdio>
#include<cstdlib>
#define R register unsigned int
#define I inline
#define YL 51061
#define lc c[x][0]
#define rc c[x][1]
#define mul(x) x*=c;x%=YL
#define add(x,c) x+=c;x%=YL
#define G ch=getchar()
#define gc G;while(ch<'*')G
#define in(z) gc;z=ch&15;G;while(ch>'*')z*=10,z+=ch&15,G;
const int N=100009;
unsigned int n,f[N],c[N][2],v[N],s[N],sz[N],lm[N],la[N],st[N];
bool r[N];
I bool nroot(R x){//好像Dalao都写的是isroot
return c[f[x]][0]==x||c[f[x]][1]==x;
}
I void pushup(R x){
s[x]=(s[lc]+s[rc]+v[x])%YL;
sz[x]=sz[lc]+sz[rc]+1;
}
I void pushr(R x){//翻转
R t=lc;lc=rc;rc=t;r[x]^=1;
}
I void pushm(R x,R c){//乘
mul(s[x]);mul(v[x]);mul(lm[x]);mul(la[x]);
}
I void pusha(R x,R c){//加
add(s[x],c*sz[x]);add(v[x],c);add(la[x],c);
}
I void pushdown(R x){
if(lm[x]!=1)pushm(lc,lm[x]),pushm(rc,lm[x]),lm[x]=1;
if(la[x]) pusha(lc,la[x]),pusha(rc,la[x]),la[x]=0;
if(r[x]) {if(lc)pushr(lc);if(rc)pushr(rc);r[x]=0;}
}
I void rotate(R x){
R y=f[x],z=f[y],k=c[y][1]==x,w=c[x][!k];
if(nroot(y))c[z][c[z][1]==y]=x;c[x][!k]=y;c[y][k]=w;//注意if(nroot(y)),本蒟蒻经常忘写
if(w)f[w]=y;f[y]=x;f[x]=z;
pushup(y);
}
I void splay(R x){
R y=x,z=0;
st[++z]=y;//手动放个栈
while(nroot(y))st[++z]=y=f[y];
while(z)pushdown(st[z--]);
while(nroot(x)){
y=f[x];z=f[y];
if(nroot(y))
rotate((c[y][0]==x)^(c[z][0]==y)?x:y);
rotate(x);
}
pushup(x);
}
I void access(R x){
for(R y=0;x;x=f[y=x])
splay(x),rc=y,pushup(x);
}
I void makeroot(R x){
access(x);
splay(x);
pushr(x);
}
I void split(R x,R y){
makeroot(x);
access(y);
splay(y);
}
I void link(R x,R y){
makeroot(x);f[x]=y;
}
I void cut(R x,R y){
split(x,y);f[x]=c[y][0]=0;
}
int main()
{
register char ch;
R q,i,a,b,k;
in(n);in(q);
for(i=1;i<=n;++i)v[i]=sz[i]=lm[i]=1;//注意乘法标记的初值为1
for(i=1;i<n;++i){
in(a);in(b);
link(a,b);
}
while(q--){
gc;
switch(ch){
case '+':
in(a);in(b);in(k);
split(a,b);pusha(b,k);
break;
case '-':
in(a);in(b);cut(a,b);
in(a);in(b);link(a,b);
break;
case '*':
in(a);in(b);in(k);
split(a,b);pushm(b,k);
break;
case '/':
in(a);in(b);
split(a,b);
printf("%d\n",s[b]);
}
}
return 0;
}
洛谷P1501 [国家集训队]Tree II(LCT,Splay)的更多相关文章
- 洛谷P1501 [国家集训队]Tree II(LCT)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- 洛谷 P1501 [国家集训队]Tree II 解题报告
P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...
- 洛谷P1501 [国家集训队]Tree II(打标记lct)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- [洛谷P1501] [国家集训队]Tree II(LCT模板)
传送门 这是一道LCT的板子题,说白了就是在LCT上支持线段树2的操作. 所以我只是来存一个板子,并不会讲什么(再说我也不会,只能误人子弟2333). 不过代码里的注释可以参考一下. Code #in ...
- 洛谷.1501.[国家集训队]Tree II(LCT)
题目链接 日常zz被define里没取模坑 //标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int //*sz[]别忘了.. #include < ...
- 【刷题】洛谷 P1501 [国家集训队]Tree II
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- [洛谷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$, ...
- 洛谷 P1501 [国家集训队]Tree II
看来这个LCT板子并没有什么问题 #include<cstdio> #include<algorithm> using namespace std; typedef long ...
- 洛谷 P1501 [国家集训队]Tree II Link-Cut-Tree
Code: #include <cstdio> #include <algorithm> #include <cstring> #include <strin ...
随机推荐
- LocalMaxima_NOI导刊2009提高(1)
先打表,发现\(ans=\sum_{i=1}^n\frac{1}{i}\) 对于小数据可以直接打表 数据很大时,精度相对就比较宽松 欧拉-马斯刻若尼常数=调和级数-自然对数 调和级数为:\(\sum_ ...
- [记]Debian alias 设置, 不设置貌似有点不方便习惯
备忘录,记录下. 不知道 当前有那些 alias 的话 直接输入 alias ,回车就可以看到 alias 列表. 终端输入: vim ~/bash_aliases 然后输入: # some more ...
- Android查缺补漏(IPC篇)-- 进程间通讯基础知识热身
本文作者:CodingBlock 文章链接:http://www.cnblogs.com/codingblock/p/8479282.html 在Android中进程间通信是比较难的一部分,同时又非常 ...
- Linux进程作业常用命令
从鸟哥的私房菜书里摘抄的部分,方便查阅 一.作业管理 1.直接将命令放到后台执行的& 如想将/etc 备份为/tmp/ect.tar.gz时不想等待,可以这样做: ...
- Visual Studio 2017 发布 15.5 版本,百度网盘离线安装包下载。
Visual Studio 2017 15.5 版本已正式发布,同时发布的还有 Visual Studio for Mac 7.3 .此次更新包含主要性能改进,新特性以及 bug 修复.发行说明中文版 ...
- java对excel表格上传和下载的处理方法
详见:http://www.jb51.net/article/120443.htm
- Asp.Net Core 2.1+的视图缓存(响应缓存)
响应缓存Razor 页与 ASP.NET 核心 2.0 中不支持. 此功能将支持ASP.NET 核心 2.1 版本. 在老的版本的MVC里面,有一种可以缓存视图的特性(OutputCache),可以保 ...
- Dockerfile 编译安装mysql5.7 千万不要执行.只是记录一下编译安装罢了
开启所有核心make 20G 内存都不够玩,跑3-4个核心吧,还好. 最后的出来的镜像3G多,百思不得其解,看了官方的Dockerfile,也没什么特别,就是 apt 或者 yum.好吧,不知做了什 ...
- webTest-----webUI自动化框架
webTest框架介绍 地址 https://github.com/wuranxu/webTest 希望大家能够喜欢!!! 简介 本框架基于Python3+selenium3+unittest组成,用 ...
- Hive数据倾斜总结
倾斜的原因: 使map的输出数据更均匀的分布到reduce中去,是我们的最终目标.由于Hash算法的局限性,按key Hash会或多或少的造成数据倾斜.大量经验表明数据倾斜的原因是人为的建表疏忽或业务 ...