题目描述

一棵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 (伍一鸣)

全程自己YY,调了一下午真累啊QWQ......

LCT的板子题,要维护子树和,加法标记,乘法标记和自身的值

放标记的时候先放乘法标记

至于为什么http://www.cnblogs.com/zwfymqz/p/8588693.html

// luogu-judger-enable-o2
#include<iostream>
#include<cstdio>
#include<cstring>
#define int long long
const int mod = ;
using namespace std;
const int MAXN = 1e5+;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') {x = x * + c - ''; c = getchar();}
return x * f;
}
int N, Q;
#define ls(x) T[x].ch[0]
#define rs(x) T[x].ch[1]
#define fa(x) T[x].f
struct node {
int f, ch[], r, mul, add, siz, sum, val;
}T[MAXN];
bool IsRoot(int x) {
return T[fa(x)].ch[] != x && T[fa(x)].ch[] != x;
}
int ident(int x) {
return T[fa(x)].ch[] == x ? : ;
}
void connect(int x, int fa, int how) {
T[x].f = fa;
T[fa].ch[how] = x;
}
void update(int x) {
T[x].sum = (T[ls(x)].sum + T[rs(x)].sum + T[x].val ) % mod;
T[x].siz = T[ls(x)].siz + T[rs(x)].siz + ;
}
void rotate(int x) {
int Y = fa(x), R = fa(Y), Yson = ident(x), Rson = ident(Y);
int B = T[x].ch[Yson ^ ];
T[x].f = R;
if(!IsRoot(Y))
connect(x, R, Rson);
connect(B, Y, Yson);
connect(Y, x, Yson ^ );
update(Y);update(x);
}
void pushr(int x) {
if(T[x].r) {
swap(ls(x), rs(x));
T[ls(x)].r ^= ;
T[rs(x)].r ^= ;
T[x].r = ;
}
}
void pushmul(int x) {
T[ls(x)].val *= T[x].mul; T[ls(x)].val %= mod;
T[rs(x)].val *= T[x].mul; T[rs(x)].val %= mod;
T[ls(x)].sum *= T[x].mul; T[ls(x)].sum %= mod;
T[rs(x)].sum *= T[x].mul; T[rs(x)].sum %= mod;
T[ls(x)].add *= T[x].mul; T[ls(x)].add %= mod;
T[rs(x)].add *= T[x].mul; T[rs(x)].add %= mod;
T[ls(x)].mul *= T[x].mul; T[ls(x)].mul %= mod;
T[rs(x)].mul *= T[x].mul; T[rs(x)].mul %= mod;
T[x].mul = ;
}
void pushadd(int x) {
T[ls(x)].val += T[x].add; T[ls(x)].val %= mod;
T[rs(x)].val += T[x].add; T[rs(x)].val %= mod;
T[ls(x)].sum += T[ls(x)].siz * T[x].add; T[ls(x)].sum %= mod;
T[rs(x)].sum += T[rs(x)].siz * T[x].add; T[rs(x)].sum %= mod;
T[ls(x)].add += T[x].add; T[ls(x)].add %= mod;
T[rs(x)].add += T[x].add; T[rs(x)].add %= mod;
T[x].add = ;
}
void pushdown(int x) {
pushr(x);
pushmul(x);
pushadd(x);
}
int st[MAXN];
int fuck;
void splay(int x) {
int y = x, top = ;
st[++top] = y;
while(!IsRoot(y)) st[++top] = (y = fa(y));
while(top) pushdown(st[top--]);
for(int y = fa(x); !IsRoot(x); rotate(x), y = fa(x))
if(!IsRoot(y))
rotate( ident(x) == ident(y) ? y : x );
}
void access(int x) {
for(int y = ; x; x = fa(y = x))//tag
splay(x), rs(x) = y, update(x);
}
void makeroot(int x) {
access(x);
splay(x);
T[x].r ^= ;
}
void split(int x,int y) {
makeroot(x);
access(y);
splay(y);
}
void link(int x, int y) {
makeroot(x);
T[x].f = y;
}
int findroot(int x) {
access(x);
splay(x);
while(ls(x)) x = ls(x);
return x;
}
void cut(int x, int y) {
split(x, y);
//makeroot(x);
if(findroot(y) == x && fa(x) == y && !rs(x))
T[x].f = T[y].ch[] = , update(y);
}
main() {
freopen("a.in","r",stdin);
scanf("%lld%lld", &N, &Q);
for(int i = ; i <= N; i++)
T[i].val = , T[i].sum = , T[i].mul = , T[i].siz = , T[i].add = ;
for(int i = ; i <= N - ; i++) {
int x = read(), y = read();
link(x, y);
}
int fuck = ;
while(Q--) {
char c = ; int u1, v1, u2, v2, val;
while(c < '*') c = getchar();
scanf("%lld%lld", &u1, &v1);
if(c == '+') {
scanf("%lld", &val);
split(u1, v1);
T[v1].val += val; T[v1].val %= mod;
T[v1].add += val; T[v1].add %= mod;
T[v1].sum += T[v1].siz * val; T[v1].sum %= mod;
}
else if(c == '-') {
scanf("%lld%lld", &u2, &v2);
cut(u1, v1);
link(u2, v2);
}
else if(c == '/') {
split(u1, v1);
printf("%d\n",T[v1].sum%mod);
}
else {
scanf("%lld",&val);
split(u1, v1);
T[v1].val *= val; T[v1].val %= mod;
T[v1].sum *= val; T[v1].siz %= mod;
T[v1].add *= val; T[v1].add %= mod;
T[v1].mul *= val; T[v1].mul %= mod;
}
}
return ;
}

洛谷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(打标记lct)

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

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

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

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

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

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

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

  7. [洛谷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$, ...

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

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

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

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

随机推荐

  1. 【element+vue后台页面】Vue-element-admin

    https://segmentfault.com/a/1190000009275424

  2. Android学习笔记(1)----播放音乐文件

    原文地址:http://www.cnblogs.com/wynet/p/5526905.html 这里介绍两种播放资源文件的方法: 第一种. assets类资源放在工程根目录的assets子目录下,它 ...

  3. arcgis for js/flex/sl 该选哪一个?

    arcgis server开发webgis 在客户端有3种选择:js.flex.sl 他们除了开发arcgis外,本身还有一些常用的领域 js:在传统网站中很常用 flex:游戏.视频播放.动画特效 ...

  4. App更新之dialog数字进度条

    App更新之dialog数字进度条 前言:现在一般的Android软件都是需要不断更新的,当你打开某个app的时候,如果有新的版本,它会提示你有新版本需要更新.当有更新时,会弹出一个提示框,点击下载, ...

  5. Week2——提交表单后后台的工作

    在我理解看来,发生请求后主要是通过域进行相互间的协调作用的.表单数据可以从request域中获得,也可以通过response域返回数据给前台. 当发起http请求后,已经启动的Tomcat服务器解析收 ...

  6. MessageFormat使用记录

    1.日志里面需要记录入参,之前一般使用StringUtils.formt()方法,但是如果入参含有空值,就会报错.这个时候可以使用MessageFormat方法.用法 format(String pa ...

  7. Protocol Buffer学习笔记

    Protocol Buffer Protobuf基础概念 Protobuf是google开发的数据结构描述语言,能够将结构化数据序列化与反序列化,取代json和xml,常用于服务器通信协议.RPC系统 ...

  8. 2.java相对路径与绝对路径

    1.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或目录在硬盘上真正的路径,(URL和物理路径)例如:C:xyz/test.txt 代表了test.txt文件的绝对路径.http://www. ...

  9. 自动化测试基础篇--Selenium框架设计(POM)

    一.自动化测试框架 感谢木棉花的漂泊分享,内容转自链接:http://www.cnblogs.com/fengyiru6369/p/8053035.html 1.什么是自动化测试框架 简单来说,自动化 ...

  10. margin的用法

    margin塌陷问题 当时说到了盒模型,盒模型包含着margin,为什么要在这里说margin呢?因为元素和元素在垂直方向上margin里面有坑. 我们来看一个例子: html结构: <div ...