题目

 一棵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行,每行描述一个操作

输出格式

  对于每个/对应的答案输出一行

输入样例

3 2

1 2

2 3

  • 1 3 4

/ 1 1

输出样例

4

题解

好久没敲LCT了。都快忘了【本来也没敲过几次】

一道很裸的板题,只是标记多了些,不过也是很经典的乘法 + 加法标记

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u]; k != -1; k = ed[k].nxt)
#define isrt(u) (!e[u].f || (e[e[u].f].ch[0] != u && e[e[u].f].ch[1] != u))
#define isr(u) (e[e[u].f].ch[1] == u)
#define ls e[u].ch[0]
#define rs e[u].ch[1]
using namespace std;
const int maxn = 100005,maxm = 200005,INF = 1000000000,P = 51061;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int h[maxn],ne = 0,N,Q;
struct EDGE{int to,nxt;}ed[maxm];
struct node{LL ch[2],f,plu,tim,w,sum,rev,siz;}e[maxn];
inline void build(int u,int v){
ed[ne] = (EDGE){v,h[u]}; h[u] = ne++;
ed[ne] = (EDGE){u,h[v]}; h[v] = ne++;
}
void pup(int u){
e[u].sum = (e[u].w + e[ls].sum + e[rs].sum) % P;
e[u].siz = e[ls].siz + e[rs].siz + 1;
}
void pd(int u){
if (e[u].tim != 1){
e[ls].w = e[ls].w * e[u].tim % P;
e[rs].w = e[rs].w * e[u].tim % P;
e[ls].sum = e[ls].sum * e[u].tim % P;
e[rs].sum = e[rs].sum * e[u].tim % P;
e[ls].plu = e[ls].plu * e[u].tim % P;
e[rs].plu = e[rs].plu * e[u].tim % P;
e[ls].tim = e[ls].tim * e[u].tim % P;
e[rs].tim = e[rs].tim * e[u].tim % P;
}
if (e[u].plu){
e[ls].w = (e[ls].w + e[u].plu) % P;
e[rs].w = (e[rs].w + e[u].plu) % P;
e[ls].sum = (e[ls].sum + (LL)e[ls].siz * e[u].plu % P) % P;
e[rs].sum = (e[rs].sum + (LL)e[rs].siz * e[u].plu % P) % P;
e[ls].plu = (e[ls].plu + e[u].plu) % P;
e[rs].plu = (e[rs].plu + e[u].plu) % P;
}
if (e[u].rev){
swap(ls,rs);
e[ls].rev ^= 1;
e[rs].rev ^= 1;
}
e[u].plu = e[u].rev = 0; e[u].tim = 1;
}
void push_down(int u){if (!isrt(u)) push_down(e[u].f); pd(u);}
void spin(int u){
int s = isr(u),fa = e[u].f;
e[u].f = e[fa].f;
if (!isrt(fa)) e[e[fa].f].ch[isr(fa)] = u;
e[fa].ch[s] = e[u].ch[s ^ 1];
if (e[u].ch[s ^ 1]) e[e[u].ch[s ^ 1]].f = fa;
e[fa].f = u;
e[u].ch[s ^ 1] = fa;
pup(fa);pup(u);
}
void splay(int u){
push_down(u);
while (!isrt(u)){
if (isrt(e[u].f)) spin(u);
else if (isr(u) ^ isr(e[u].f)) spin(u),spin(u);
else spin(e[u].f),spin(u);
}
}
void Access(int u){
int v = 0;
while (u) splay(u),rs = v,e[v].f = u,pup(u),u = e[v = u].f;
}
void Make_root(int u){Access(u); splay(u); e[u].rev ^= 1;}
void Link(int u,int v){
Make_root(u); Access(v); splay(v);
e[u].f = v; pup(v);
}
void Cut(int u,int v){
Make_root(u); Access(v); splay(v);
e[v].ch[0] = e[u].f = 0; pup(v);
}
LL Query(int u,int v){
Make_root(u); Access(v); splay(v);
return e[v].sum;
}
void Add(int u,int v,LL w){
Make_root(u); Access(v); splay(v);
e[v].w = (e[v].w + w) % P;
e[v].plu = (e[v].plu + w) % P;
e[v].sum = (e[v].sum + (LL)w * e[v].siz % P) % P;
}
void Tim(int u,int v,LL w){
Make_root(u); Access(v); splay(v);
e[v].w = (e[v].w * w) % P;
e[v].sum = (e[v].sum * w) % P;
e[v].tim = (e[v].tim * w) % P;
e[v].plu = (e[v].plu * w) % P;
}
void dfs(int u){
Redge(u) if (ed[k].to != e[u].f){
e[ed[k].to].f = u;
dfs(ed[k].to);
}
}
int main(){
memset(h,-1,sizeof(h));
N = RD(); Q = RD(); REP(i,N - 1) build(RD(),RD());
REP(i,N) e[i].sum = e[i].w = e[i].tim = e[i].siz = 1;
dfs(1); char opt; int u,v,u1,v1;
while (Q--){
opt = getchar();
while (opt != '+' && opt != '-' && opt != '*' && opt != '/') opt = getchar();
u = RD(); v = RD();
if (opt == '+') Add(u,v,RD());
else if (opt == '-') u1 = RD(),v1 = RD(),Cut(u,v),Link(u1,v1);
else if (opt == '*') Tim(u,v,RD());
else if (opt == '/') printf("%lld\n",Query(u,v));
}
return 0;
}

BZOJ2631 tree 【LCT】的更多相关文章

  1. [BZOJ - 2631] tree 【LCT】

    题目链接:BZOJ - 2631 题目分析 LCT,像线段树区间乘,区间加那样打标记. 这道题我调了一下午. 提交之后TLE了,我一直以为是写错了导致了死循环. 于是一直在排查错误.直到.. 直到我看 ...

  2. [BZOJ 3282] Tree 【LCT】

    题目链接:BZOJ - 3282 题目分析 这道题是裸的LCT,包含 Link , Cut 和询问两点之间的路径信息. 写代码时出现的错误:Access(x) 的循环中应该切断的是原来的 Son[x] ...

  3. 3282. Tree【LCT】

    Description 给定N个点以及每个点的权值,要你处理接下来的M个操作. 操作有4种.操作从0到3编号.点从1到N编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和 ...

  4. 606. Construct String from Binary Tree 【easy】

    606. Construct String from Binary Tree [easy] You need to construct a string consists of parenthesis ...

  5. 【HDU4010】【LCT】Query on The Trees

    Problem Description We have met so many problems on the tree, so today we will have a query problem ...

  6. 【BZOJ2049】【LCT】Cave 洞穴勘测

    Description 辉 辉热衷于洞穴勘测.某天,他按照地图来到了一片被标记为JSZX的洞穴群地区.经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通 道组成,并且每条通道连接了 ...

  7. 543. Diameter of Binary Tree【Easy】【二叉树的直径】

    Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...

  8. 【LCT】一步步地解释Link-cut Tree

    简介 Link-cut Tree,简称LCT. 干什么的?它是树链剖分的升级版,可以看做是动态的树剖. 树剖专攻静态树问题:LCT专攻动态树问题,因为此时的树剖面对动态树问题已经无能为力了(动态树问题 ...

  9. ZJOI2012网络 题解报告【LCT】

    题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相同颜色的边不超过两条. 图中不存在同色的环,同色的环指相同颜色的边构成的环. 在这 ...

随机推荐

  1. 解决mysql远程连接失败的问题

    问题描述 在我远程连接我的服务器数据库的时候,navicat给我提示了这么一个错误: ERROR : Host 'xxx' is not allowed to connect to thisMySQL ...

  2. 有一段<script>代码,效果是点击<p>就会弹出信息,但是有的<p>点击会有效果,有的没有效果

    问题:有一段<script>代码,效果是点击<p>就会弹出信息,但是有的<p>点击会有效果,有的没有效果 解决: 页面代码是至上而下执行的,如果你的这个标签在< ...

  3. php mysql find_in_set函数 检索单子段 逗号分隔序列

    FIND_IN_SET($kwd,field) 例如在 表 AA中 numbers 字段  保存列数据 1,4,8,75,41,7 就可以使用  FIND_IN_SET(8,numbers)  查询记 ...

  4. 判断移动端和pc端最简单的方法

    <!DOCTYPE html><html><head> <title></title> <script type="text ...

  5. jquery 配合 ajax 完成 在线编辑 你值得拥有

    思路分析: 将 table中的表格 改变成为 input表格框获得值 ajax配合修改 删除 <?php use yii\helpers\Url; $web = Url::base(); ?&g ...

  6. 手动完全卸载Office

    1 当然出现安装错误,或是无法安装先考虑官方卸载工具卸载,运行后要是解决了问题是最好的.毕竟手动删除比较麻烦. 开始我们先停止 Office Source Engine 服务.以windows7为例子 ...

  7. 分离链接法(Separate Chaining)

    之前我们说过,对于需要动态维护的散列表 冲突是不可避免的,无论你的散列函数设计的有多么精妙.因此我们解决的重要问题就是:一旦发生冲突,我们该如何加以排解? 我们在这里讨论最常见的两种方法:分离链接法和 ...

  8. 笔记-python-redis接口

    笔记-python-redis接口 1.      python 与redis接口 redis是redis数据库的python接口包,为python提供的redis的调用接口. 注:文档内容主要基于h ...

  9. TouTiao开源项目 分析笔记17 新闻媒体专栏

    1.效果预览 1.1.要实现的效果 1.2.如何调转到新闻媒体专栏 点击右上角的用户图标. 在新闻详情页面的Fragment的菜单点击事件中触发. case R.id.action_open_medi ...

  10. Java线程和多线程(五)——单例类中的线程安全

    单例模式是最广泛使用的创建模式之一.在现实世界之中,诸如Databae的连接或者是企业信息系统(EIS)等,通常其创建都是受到限制的,应该尽量复用已存在对象而不是频繁创建销毁.为了达到这个目的,开发者 ...