洛谷.1501.[国家集训队]Tree II(LCT)
日常zz被define里没取模坑
//标记下放同线段树 注意51061^2 > 2147483647,要开unsigned int
//*sz[]别忘了。。
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define mod (51061)
typedef unsigned int uint;
const int N=1e5+5;
inline int read()
{
int now=0;register char c=gc();
for(;!isdigit(c);c=gc());
for(;isdigit(c);now=now*10+c-'0',c=gc());
return now;
}
namespace LCT
{
#define lson son[x][0]
#define rson son[x][1]
#define ADD(x,v) (x)+=(v), (x)%=mod//直接这样最快
// #define ADD(x,v) (x)+=(v), (x)>=mod?(x)-=mod:0
// #define ADD(x,v) (x)+=(v); if((x)>=mod) (x)-=mod//比上一行快一点
int son[N][2],fa[N],sk[N],sz[N];
uint val[N],sum[N],m_tag[N],a_tag[N];
bool r_tag[N];
inline void Update(int x){
sz[x]=sz[lson]+sz[rson]+1;
sum[x]=(sum[lson]+sum[rson]+val[x])%mod;
}
inline void Rev(int x){
std::swap(lson,rson), r_tag[x]^=1;
}
inline void Mult(int x,uint v){
(sum[x]*=v)%=mod, (val[x]*=v)%=mod, (m_tag[x]*=v)%=mod, (a_tag[x]*=v)%=mod;
}
inline void Add(int x,uint v){
// sum[x]+=v*sz[x]%mod, sum[x]>=mod?sum[x]-=mod:0, val[x]+=v, val[x]>=mod?val[x]-=mod:0, a_tag[x]+=v, a_tag[x]>=mod?a_tag[x]-=mod:0;
// ADD(sum[x],v*sz[x]%mod/*2.3 ADD这要取模!*/); ADD(val[x],v); ADD(a_tag[x],v);
ADD(sum[x],v*sz[x]); ADD(val[x],v); ADD(a_tag[x],v);
}
void PushDown(int x){
if(m_tag[x]!=1) Mult(lson,m_tag[x]),Mult(rson,m_tag[x]),m_tag[x]=1;
if(a_tag[x]) Add(lson,a_tag[x]),Add(rson,a_tag[x]),a_tag[x]=0;
if(r_tag[x]) Rev(lson),Rev(rson),r_tag[x]=0;
}
inline bool n_root(int x){
return son[fa[x]][0]==x||son[fa[x]][1]==x;
}
void Rotate(int x)
{
int a=fa[x],b=fa[a],l=son[a][1]==x,r=l^1;
if(n_root(a)) son[b][son[b][1]==a]=x;
if(son[x][r]) fa[son[x][r]]=a;
fa[a]=x, fa[x]=b, son[a][l]=son[x][r], son[x][r]=a;
Update(a);
}
void Splay(int x)
{
int t=1,a=x,b; sk[1]=x;
while(n_root(a)) sk[++t]=a=fa[a];
while(t) PushDown(sk[t--]);
while(n_root(x))
{
a=fa[x],b=fa[a];
if(n_root(a)) Rotate(son[a][1]==x^son[b][1]==a?x:a);
Rotate(x);
}
Update(x);
}
void Access(int x){
for(int pre=0; x; x=fa[pre=x])
Splay(x), rson=pre, Update(x);
}
void Make_root(int x){
Access(x), Splay(x), Rev(x);
}
void Split(int x,int y){
Make_root(x), Access(y), Splay(y);
}
// int Find_root(int x){
// Access(x), Splay(x);
// while(lson) x=lson;
// return x;
// }
void Link(int x,int y){
Make_root(x), fa[x]=y;
}
void Cut(int x,int y){
Split(x,y), fa[x]=son[y][0]=0, Update(y);
// Make_root(x);
// if(Find_root(y)==x&&fa[x]==y&&!rson)
// fa[x]=son[y][0]=0, Update(y);
}
}
int main()
{
int n=read(),q=read();
for(int i=1; i<=n; ++i) LCT::sz[i]=LCT::sum[i]=LCT::val[i]=LCT::m_tag[i]=1;
for(int u,v,i=1; i<n; ++i) u=read(),v=read(),LCT::Link(u,v);
int u,v,c,d; char opt[3];
while(q--)
{
scanf("%s",opt),u=read(),v=read();
if(opt[0]=='+') c=read(),LCT::Split(u,v),LCT::Add(v,c);
else if(opt[0]=='-') c=read(),d=read(),LCT::Cut(u,v),LCT::Link(c,d);
else if(opt[0]=='*') c=read(),LCT::Split(u,v),LCT::Mult(v,c);
else LCT::Split(u,v),printf("%d\n",LCT::sum[v]);
}
return 0;
}
洛谷.1501.[国家集训队]Tree II(LCT)的更多相关文章
- 洛谷P1501 [国家集训队]Tree II(LCT)
题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...
- 洛谷 1501 [国家集训队]Tree II BZOJ 2631 Tree
[题解] 维护乘法标记和加法标记的LCT #include<cstdio> #include<algorithm> #define Mod (51061) #define N ...
- 洛谷 P1501 [国家集训队]Tree II 解题报告
P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...
- 洛谷P1501 [国家集训队]Tree II(LCT,Splay)
洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...
- 洛谷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 ...
- 【刷题】洛谷 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 ...
随机推荐
- Python3 日期时间 相关模块(time(时间) / datatime(日期时间) / calendar(日历))
Python3 日期时间 相关模块(time(时间) / datatime(日期时间) / calendar(日历)) 本文由 Luzhuo 编写,转发请保留该信息. 原文: http://blog. ...
- MR数据生成工具指向目录
mrDataTidy_SaveTwoDays.jar 原始路径 :D:\太原MR数据\一天数据整理 目标路径 : D:\MR现场数据整理\保存两天_整理后数据 例如 当前时间:2017-5-17 10 ...
- chattr的使用
让某个文件只能往里面追加内容,不能删除,一些日志文件适用于这种操作: chattr +a /home/caolei/.bash_history 查看lsattr /home/caolei/.bash_ ...
- 网络抓包 Fiddler
1. Fiddler 抓包简介 Fiddler是通过改写HTTP代理,让数据从它那通过,来监控并且截取到数据.当然Fiddler很屌,在打开它的那一瞬间,它就已经设置好了浏览器的代理了.当你关闭的时候 ...
- 如何判断mac地址时multicast还是broadcast ?
ethernet 的地址其实就是mac地址,长度为6 byte,其中有一位为 multicast bit 位. 当unicast/multicast bit 位置1时就是 multicast,mac ...
- windows安装配置git和Tortoisegit
git github gitlab Tortoisegit 的概念自行百度 1. 安装git 2. 安装小乌龟:Tortoisegit 和中文包 3. 配置 4. 使用 参考: 目录 安装及配置 ...
- python3内存存储几种数据类型对差异
列表,元组,集合,字典几种数据类型差异 列表: list=[0,1,'a'] 元组:list=(0,1,'a') 集合 :list=[0,1,'a'] 字典:list={name:'tom',age: ...
- java 数据的存储
1. 寄存器. 这是最快的存储区,因为它位于不同于其他存储区的地方 -- 处理器的内部.但是寄存器的数量极其有限,所以寄存器根据需求进行分配.你不能直接控制,也不能在程序中感觉到寄存器存在的任何迹象. ...
- 两道SQL题目
1.查询省内所有城市气温都大于35度的省份(表名:Temp) SELECT province FROM Temp WHERE province NOT IN ( SELECT province FRO ...
- 5个php实例,细致说明传值与传引用的区别
传值:是把实参的值赋值给行参 ,那么对行参的修改,不会影响实参的值 传引用 :真正的以地址的方式传递参数传递以后,行参和实参都是同一个对象,只是他们名字不同而已对行参的修改将影响实参的值 说明: 传值 ...