题目描述

一棵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. vs code上配置Scala

    转自:https://www.cnblogs.com/steven-yang/p/5852988.html 百度的结果表达太奇怪,简单记一笔. 1.下载一个scala的压缩包,https://www. ...

  2. GNU工具 ar

    1.ar基本用法 ar命令可以用来创建.修改库,也可以从库中提出单个模块.库是一单独的文件,里面包含了按照特定的结构组织起来的其它的一些文件(称做此库文件的member).原始文件的内容.模式.时间戳 ...

  3. YC

    package com.hanqi; import java.util.*; public class yc{ public static void main(String[] args) { // ...

  4. Linux常用命令(一)————查找和替换

    1. 查找一个字符串 一个字符串是一行上的一个或几个字符.    为查找一个字符串,在vi命令模式下键入“/”,后面跟要查找的字符串,再按回车.vi将光标定位在该串下一次出现的地方上.键入n跳到该串的 ...

  5. CentOS随笔 - 6.CentOS7安装Git服务器

    前言 转帖请注明出处: http://www.cnblogs.com/Troy-Lv5/ 版本管理当然是选择git..反正我是被svn坑怕了... 这次安装的是git 2.18.0 点击下载 准备安装 ...

  6. SCCM2007日志文件

    Microsoft System Center Configuration Manager 2007 中的所有客户端和站点服务器组件都将过程信息记录在单个日志文件中.您可以使用客户端和站点服务器日志文 ...

  7. Java代码实现对Azkaban的Flow进行设置定时

    代码如下: public class CurlToAzkaban{ public static void scheduleExecute(String flow, String cronExpress ...

  8. 一个简单的php分页逻辑

    php分页 <?php include 'backend/conn.php'; $html = '<ul>'; //输出的html $pageDataNum=3; //每页显示10行 ...

  9. JS:二维数组排序和获取子级元素

    JS:二维数组排序和获取子级元素 1. 二维数组排序 1.按数值排序 var arr = [[1, 2, 3], [7, 2, 3], [3, 2, 3]]; 如果我们要按每个子数组的第一列来排序要如 ...

  10. #Alpha Scrum6

    Alpha Scrum6 牛肉面不要牛肉不要面 Alpha项目冲刺(团队作业5) 各个成员在 Alpha 阶段认领的任务 林志松:督促和监督团队进度 陈彬:博客编写 吴沂章.林锃寒:代码功能完善 林志 ...