题目描述

一棵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. [算法练习]String to Integer (atoi)

    题目说明: Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input ...

  2. Mac下完全删除GarageBand

    https://www.tekrevue.com/tip/delete-garageband/ 已从应用程序列表删除,/资源库/Application Support/GarageBand/里的也删除 ...

  3. visual studio code 输出乱码

    问题: 解决方法: 首先,这个与VS本身无关,问题是出现在windows的dos显示设置上. 如何解决这个问题? 1.打开运行,输入cmd: 2.界面顶部右键,选择默认值: 3.将437(OEM-美国 ...

  4. 自动化测试基础篇--Selenium unittest简介

    一.什么是unittest unittest是Python单元测试框架,类似于JUnit框架. unittest中有4个重要的概念:test fixture, test case, test suit ...

  5. 五、python小功能记录——打包程序

    使用pyinstaller打包Python程序 安装工具 :pip3 install pyinstaller 在Python程序文件夹上(不点进去)按住shift并且右键,在弹出的选项中点击" ...

  6. 【Leetcode】【Hard】Copy List with Random Pointer

    A linked list is given such that each node contains an additional random pointer which could point t ...

  7. Excel英语成绩单 吴昊

  8. ASP.NET Core Startup类 Configure()方法 | ASP.NET Core 中间件详细说明

    ASP.NET Core 程序启动过程如下 目录 Startup 类 Configure() 方法 中间件 使用中间件 Configure 方法 的参数 IApplicationBuilder Ext ...

  9. UNIX crontab自动执行脚本

    crontab 是不会加载环境变量的你手动执行可以是因为登录了oracle用户加载了环境变量,你可以在脚本里添加,echo $ORACLE_HOME  echo $ORACLE_SID 等等试试,看看 ...

  10. socket端口复用问题一二

    实际上,默认的情况下,如果一个网络应用程序的一个套接字 绑定了一个端口( 占用了 8000 ),这时候,别的套接字就无法使用这个端口( 8000 ), 验证例子如下: #include <std ...