题目大意:维护一种树形数据结构。支持下面操作:

1.树上两点之间的点权值+k。

2.删除一条边。添加一条边,保证加边之后还是一棵树。

3.树上两点之间点权值*k。

4.询问树上两点时间点的权值和。

思路:利用动态树维护这棵树,lct的裸题。假设不会下传标记的,先去做BZOJ1798,也是这种标记,仅仅只是在线段树上做,比这个要简单很多。

这个也是我的LCT的第一题,理解起来十分困难啊。。。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define MO 51061
using namespace std; struct Complex{
int size;
unsigned int val,sum;
Complex *son[2],*father;
bool reverse;
int m_mark,p_mark; bool Check() {
return father->son[1] == this;
}
void Reverse();
void Plus(unsigned int c);
void Mulitiply(unsigned int c);
void PushUp();
void PushDown();
}*tree[MAX],*nil = new Complex(); int cnt,points,asks;
int head[MAX],total;
int next[MAX << 1],aim[MAX << 1]; char c[10]; void Pretreatment(); inline Complex *NewComplex(unsigned int val); inline void Add(int x,int y);
void DFS(int x,int last); inline void Splay(Complex *a);
inline void Rotate(Complex *a,bool dir);
inline void PushPath(Complex *a); inline void Access(Complex *a);
inline void ToRoot(Complex *a);
inline void Link(Complex *x,Complex *y);
inline void Cut(Complex *x,Complex *y); int main()
{
Pretreatment();
cin >> points >> asks;
for(int x,y,i = 1;i < points; ++i) {
scanf("%d%d",&x,&y);
Add(x,y),Add(y,x);
}
for(int i = 1;i <= points; ++i)
tree[i] = NewComplex(1);
DFS(1,-1);
for(int x,y,z,i = 1;i <= asks; ++i) {
scanf("%s%d%d",c,&x,&y);
if(c[0] == '+') {
scanf("%d",&z);
ToRoot(tree[x]);
Access(tree[y]);
Splay(tree[y]);
tree[y]->Plus(z);
}
else if(c[0] == '-') {
Cut(tree[x],tree[y]);
scanf("%d%d",&x,&y);
Link(tree[x],tree[y]);
}
else if(c[0] == '*') {
scanf("%d",&z);
ToRoot(tree[x]);
Access(tree[y]);
Splay(tree[y]);
tree[y]->Mulitiply(z);
}
else {
ToRoot(tree[x]);
Access(tree[y]);
Splay(tree[y]);
printf("%d\n",tree[y]->sum);
}
}
return 0;
} void Complex:: PushUp()
{
sum = (son[0]->sum + son[1]->sum + val) % MO;
size = son[0]->size + son[1]->size + 1;
} void Complex:: PushDown()
{
if(m_mark != 1) {
son[0]->Mulitiply(m_mark);
son[1]->Mulitiply(m_mark);
m_mark = 1;
}
if(p_mark) {
son[0]->Plus(p_mark);
son[1]->Plus(p_mark);
p_mark = 0;
}
if(reverse) {
son[0]->Reverse();
son[1]->Reverse();
reverse = false;
}
} void Complex:: Reverse()
{
reverse ^= 1;
swap(son[0],son[1]);
} void Complex:: Plus(unsigned int c)
{
if(this == nil) return ;
val = (val + c) % MO;
p_mark = (p_mark + c) % MO;
sum = (sum + (size * c) % MO) % MO;
} void Complex:: Mulitiply(unsigned int c)
{
if(this == nil) return ;
m_mark = (m_mark * c) % MO;
val = (val * c) % MO;
p_mark = (p_mark * c) % MO;
sum = (sum * c) % MO;
} inline void Add(int x,int y)
{
next[++total] = head[x];
aim[total] = y;
head[x] = total;
} void Pretreatment()
{
nil->size = 0;
nil->son[0] = nil->son[1] = nil->father = nil;
} inline Complex *NewComplex(unsigned int val)
{
Complex *re = new Complex();
re->val = re->sum = val;
re->reverse = false;
re->son[0] = re->son[1] = re->father = nil;
re->p_mark = 0;
re->m_mark = 1;
re->size = 1;
return re;
} void DFS(int x,int last)
{
for(int i = head[x];i;i = next[i]) {
if(aim[i] == last) continue;
tree[aim[i]]->father = tree[x];
DFS(aim[i],x);
}
} inline void Splay(Complex *a)
{
PushPath(a);
while(a == a->father->son[0] || a == a->father->son[1]) {
Complex *p = a->father->father;
if(p->son[0] != a->father && p->son[1] != a->father)
Rotate(a,!a->Check());
else if(!a->father->Check()) {
if(!a->Check())
Rotate(a->father,true),Rotate(a,true);
else Rotate(a,false),Rotate(a,true);
}
else {
if(a->Check())
Rotate(a->father,false),Rotate(a,false);
else Rotate(a,true),Rotate(a,false);
}
}
a->PushUp();
} inline void Rotate(Complex *a,bool dir)
{
Complex *f = a->father;
f->son[!dir] = a->son[dir];
f->son[!dir]->father = f;
a->son[dir] = f;
a->father = f->father;
if(f->father->son[0] == f || f->father->son[1] == f)
f->father->son[f->Check()] = a;
f->father = a;
f->PushUp();
} inline void PushPath(Complex *a)
{
static Complex *stack[MAX];
int top = 0;
for(;a->father->son[0] == a || a->father->son[1] == a;a = a->father)
stack[++top] = a;
stack[++top] = a;
while(top)
stack[top--]->PushDown();
} inline void Access(Complex *a)
{
Complex *last = nil;
while(a != nil) {
Splay(a);
a->son[1] = last;
a->PushUp();
last = a;
a = a->father;
}
} inline void ToRoot(Complex *a)
{
Access(a);
Splay(a);
a->Reverse();
} inline void Link(Complex *x,Complex *y)
{
ToRoot(x);
x->father = y;
} inline void Cut(Complex *x,Complex *y)
{
ToRoot(x);
Access(y);
Splay(y);
y->son[0]->father = nil;
y->son[0] = nil;
y->PushUp();
}

BZOJ 2631 tree 动态树(Link-Cut-Tree)的更多相关文章

  1. 动态树(Link Cut Tree) :SPOJ 375 Query on a tree

    QTREE - Query on a tree #number-theory You are given a tree (an acyclic undirected connected graph) ...

  2. LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)

    为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...

  3. P3690 【模板】Link Cut Tree (动态树)

    P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...

  4. 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)

    题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...

  5. LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板

    P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...

  6. LG3690 【模板】Link Cut Tree (动态树)

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

  7. [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)

    [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...

  8. link cut tree 入门

    鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...

  9. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  10. Link Cut Tree 总结

    Link-Cut-Tree Tags:数据结构 ##更好阅读体验:https://www.zybuluo.com/xzyxzy/note/1027479 一.概述 \(LCT\),动态树的一种,又可以 ...

随机推荐

  1. vs2010永久删除项目的相关操作

    1.选中要删除的项目,在解决方案资源管理器中,直接左键点击一下即可.. 2.点击键盘的删除键“DElect”. 3.然后找到工程的目录后,删除项目.即可永久性删除不在需要的程序或者是项目.

  2. PCB 奥宝LDI 输出 轴交换与镜像关系

    持续P2 奥宝LDI改造,针对轴交换与镜像关系整理如下:(标记) 关键参数说明: 轴交换swap_axes: 当为Yes,则图形--镜像+旋转90度,当为No,则图形--不动 xmirror与ymir ...

  3. 洛谷P2916 [USACO08NOV]为母牛欢呼(最小生成树)

    P2916 [USACO08NOV]为母牛欢呼Cheering up the C… 题目描述 Farmer John has grown so lazy that he no longer wants ...

  4. go package包的使用

    一.标准库 引入 在我们之前所写的所以代码中,我们基本上可以看到fmt这个导入的包,但是我们却不知道如何去写这种包. 如果我们可以自己去写,那么我们就可以将一个功能的集合统一的放入包中,便于以后使用, ...

  5. Spring Data 自动生成

    之前一直用的mybatis逆向自动生成,由于最近学习springdata,所以看了一下springdata的自动生成,基本与mybatis一致,不同的也许就是逆向生成代码(实体类,mapper等)和正 ...

  6. SpringCloud(二) 服务注册与发现Eureka

    1.eureka是干什么的? 上篇说了,微服务之间需要互相之间通信,那么通信就需要各种网络信息,我们可以通过使用硬编码的方式来进行通信,但是这种方式显然不合适,不可能说一个微服务的地址发生变动,那么整 ...

  7. flash 遮住 div 解决办法

    被遮盖的div 下面的代码   <!--列表菜单-->             <div id="opreationmenu" style="posit ...

  8. JavaScript学习二

    2019-05-30 15:08:24 加油,这几天在赶高数,都…… <!DOCTYPE html> <html> <head> <script type=& ...

  9. angular js 公告墙

    <!DOCTYPE html>   <html lang="en">   <head>   <meta charset="UTF ...

  10. 压缩映射:简单最邻近搜索-(SLH)Simple Linear Hash

    Compact Projection: Simple and Efficient Near Neighbor Search with Practical memory Requirement Auto ...