题意

一棵树,有删边加边,有一条链加/乘一个数,有询问一条链的和

分析

LCT,像线段树一样维护两个标记(再加上翻转标记就是三个),维护size,就行了

CODE

#include<bits/stdc++.h>
using namespace std;
inline void read(int &num) {
char ch; int flg = 1; while(!isdigit(ch=getchar()))if(ch=='-')flg = -flg;
for(num=0; isdigit(ch); num=num*10+ch-'0', ch=getchar()); num*=flg;
}
const int MAXN = 100005;
const int mod = 51061;
namespace LCT {
#define ls ch[x][0]
#define rs ch[x][1]
int ch[MAXN][2], fa[MAXN], w[MAXN], sz[MAXN], mul[MAXN], add[MAXN], sum[MAXN];
bool rev[MAXN];
inline bool isr(int x) { return ch[fa[x]][0] != x && ch[fa[x]][1] != x; }
inline bool get(int x) { return ch[fa[x]][1] == x; }
inline void upd(int x) {
sum[x] = (sum[ls] + sum[rs] + w[x]) % mod;
sz[x] = sz[ls] + sz[rs] + 1;
}
inline void pusha(int x, int val) {
if(!x) return;
sum[x] = (sum[x] + 1ll * val * sz[x]) % mod;
w[x] = (w[x] + val) % mod;
add[x] = (add[x] + val) % mod;
}
inline void pushm(int x, int val) {
if(!x) return;
sum[x] = 1ll * sum[x] * val % mod;
w[x] = 1ll * w[x] * val % mod;
add[x] = 1ll * add[x] * val % mod;
mul[x] = 1ll * mul[x] * val % mod;
}
inline void mt(int x) {
if(rev[x]) rev[ls]^=1, rev[rs]^=1, rev[x]^=1, swap(ls, rs);
if(mul[x]!=1) pushm(ls, mul[x]), pushm(rs, mul[x]), mul[x] = 1;
if(add[x]) pusha(ls, add[x]), pusha(rs, add[x]), add[x] = 0;
}
void mtpath(int x) { if(!isr(x)) mtpath(fa[x]); mt(x); }
inline void rot(int x) {
int y = fa[x], z = fa[y]; bool l = get(x), r = l^1;
if(!isr(y)) ch[z][get(y)] = x;
fa[ch[x][r]] = y; fa[y] = x; fa[x] = z;
ch[y][l] = ch[x][r]; ch[x][r] = y;
upd(y), upd(x);
}
inline void splay(int x) {
mtpath(x);
for(; !isr(x); rot(x))
if(!isr(fa[x])) rot(get(fa[x])==get(x)?fa[x]:x);
}
inline int access(int x) { int y = 0;
for(; x; x=fa[y=x]) splay(x), ch[x][1] = y, upd(x);
return y;
}
inline void bert(int x) { access(x), splay(x), rev[x]^=1; }
inline int sert(int x) {
access(x), splay(x);
for(; ch[x][0]; x=ch[x][0]);
return x;
}
inline void Link(int x, int y) { bert(x); if(sert(y) != x) fa[x] = y; }
inline void Cut(int x, int y) { bert(x); if(sert(y) == x && fa[x] == y && !ch[x][1]) fa[x] = ch[y][0] = 0, upd(y); }
inline int split(int x, int y) { bert(x), access(y), splay(y); return y; }
inline void Add(int x, int y, int val) { pusha(split(x, y), val); }
inline void Mul(int x, int y, int val) { pushm(split(x, y), val); }
inline int Query(int x, int y) { return sum[split(x, y)]; }
#undef ls
#undef rs
}
using namespace LCT;
int n, q;
int main() {
//freopen("sample.txt", "r", stdin);
read(n), read(q);
for(int i = 1; i <= n; ++i)
w[i] = sum[i] = mul[i] = sz[i] = 1;
for(int i = 1, x, y; i < n; ++i)
read(x), read(y), Link(x, y);
char ch[2];
int x, y, u, v;
while(q--) {
scanf("%s", ch);
switch(ch[0]) {
case '+':
read(u), read(v), read(x), Add(u, v, x%mod);
break;
case '-':
read(u), read(v), read(x), read(y), Cut(u, v), Link(x, y);
break;
case '*':
read(u), read(v), read(x), Mul(u, v, x%mod);
break;
case '/':
read(u), read(v), printf("%d\n", Query(u, v));
break;
}
}
}

BZOJ 2631 tree / Luogu P1501 [国家集训队]Tree II (LCT,多重标记)的更多相关文章

  1. BZOJ 2631 tree | Luogu P1501 [国家集训队]Tree II (LCT 多重标记下放)

    链接:https://www.luogu.org/problemnew/show/P1501 题面: 题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: ...

  2. LUOGU P1501 [国家集训队]Tree II (lct)

    传送门 解题思路 \(lct\),比较模板的一道题,路径加和乘的维护标记与线段树\(2\)差不多,然后剩下就没啥了.但调了我将近一下午.. 代码 #include<iostream> #i ...

  3. P1501 [国家集训队]Tree II(LCT)

    P1501 [国家集训队]Tree II 看着维护吧2333333 操作和维护区间加.乘线段树挺像的 进行修改操作时不要忘记吧每个点的点权$v[i]$也处理掉 还有就是$51061^2=2607225 ...

  4. 洛谷 P1501 [国家集训队]Tree II 解题报告

    P1501 [国家集训队]Tree II 题目描述 一棵\(n\)个点的树,每个点的初始权值为\(1\).对于这棵树有\(q\)个操作,每个操作为以下四种操作之一: + u v c:将\(u\)到\( ...

  5. P1501 [国家集训队]Tree II LCT

    链接 luogu 思路 简单题 代码 #include <bits/stdc++.h> #define ls c[x][0] #define rs c[x][1] using namesp ...

  6. 洛谷P1501 [国家集训队]Tree II(LCT,Splay)

    洛谷题目传送门 关于LCT的其它问题可以参考一下我的LCT总结 一道LCT很好的练习放懒标记技巧的题目. 一开始看到又做加法又做乘法的时候我是有点mengbi的. 然后我想起了模板线段树2...... ...

  7. 【刷题】洛谷 P1501 [国家集训队]Tree II

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

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

    题目描述 一棵n个点的树,每个点的初始权值为1.对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c: - u1 v1 u2 v2:将树中原有的 ...

  9. p1501 [国家集训队]Tree II

    传送门 分析 lct板子题 单独维护一下加和乘的情况即可 维护方法和维护翻转差不多 代码 #include<iostream> #include<cstdio> #includ ...

随机推荐

  1. Python基础总结之第十天开始【认识模块、包和库】(新手可相互督促)

    每天都有一种备课的赶脚~~~ 什么是模块? 在实际的开发过程中,代码量肯定有成千上万行的代码,甚至十几万行代码也很正常吧... 那么这么多的代码如果放在一个文件中,肯定是很不合适的,为了以后程序的编写 ...

  2. Java编程思想(四)初始化和清除

    4.1用构建器自动初始化 若某个类中有一个构建器,那么在创建对象时,Java会自动调用哪个构建器    在Java中构建器的名字必须与类名相同,这样可以保证这样一个方法惠子初始化期间自动调用: 利用构 ...

  3. Java集合框架概述和集合的遍历

    第三阶段 JAVA常见对象的学习 集合框架概述和集合的遍历 (一) 集合框架的概述 (1) 集合的由来 如果一个程序只包含固定数量的且其生命周期都是已知的对象,那么这是一个非常简单的程序. 通常,程序 ...

  4. [转帖]【Oracle】详解Oracle中NLS_LANG变量的使用

    [Oracle]详解Oracle中NLS_LANG变量的使用 https://www.cnblogs.com/HDK2016/p/6880560.html NLS_LANG=LANGUAGE_TERR ...

  5. php实现只需要一个QQ号就可以获得用户信息

    <?php // 通过QQ号即可获取用户信息 // 获取QQ头像接口 // http://q1.qlogo.cn/g?b=qq&nk=QQ号&s=100&t=154790 ...

  6. luogu P4762 [CERC2014]Virus synthesis (回文自动机)

    大意: 初始有一个空串, 操作(1)在开头或末尾添加一个字符. 操作(2)在开头或末尾添加该串的逆串. 求得到串$S$所需最少操作数. 显然最后一定是由某个偶回文通过添加字符得到的, 那么只需要求出所 ...

  7. 超详细,新手都能看懂 !使用SpringBoot+Dubbo 搭建一个简单的分布式服务

    来自:JavaGuide Github 地址:https://github.com/Snailclimb/springboot-integration-examples 目录: 使用 SpringBo ...

  8. html中script标签使用async属性和defer属性的区别

    相同点: 首先async和defer只对header里的外连脚本script标签上起作用,如果script标签是放在header外或者是header里的内置脚本以及动态生成的script标签是不起作用 ...

  9. 【css】display:flex和display:box有什么区别

    说法一: 注意:前者是flex 2012年的语法,也将是以后标准的语法,大部分浏览器已经实现了无前缀版本.后者是2009年的语法,已经过时,是需要加上对应前缀的.所以兼容性的代码,大致如下displa ...

  10. JDK + Tomcat 安装 + 制作自定义镜像【第 1 篇 JDK】

    [第 1 篇 JDK]:https://www.cnblogs.com/del88/p/11842387.html[第 2 篇 Tomcat]:https://www.cnblogs.com/del8 ...