BZOJ 2631 tree 动态树(Link-Cut-Tree)
题目大意:维护一种树形数据结构。支持下面操作:
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)的更多相关文章
- 动态树(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) ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
- 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- LG3690 【模板】Link Cut Tree (动态树)
题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...
- [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)
[BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...
- link cut tree 入门
鉴于最近写bzoj还有51nod都出现写不动的现象,决定学习一波厉害的算法/数据结构. link cut tree:研究popoqqq那个神ppt. bzoj1036:维护access操作就可以了. ...
- Link Cut Tree学习笔记
从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...
- Link Cut Tree 总结
Link-Cut-Tree Tags:数据结构 ##更好阅读体验:https://www.zybuluo.com/xzyxzy/note/1027479 一.概述 \(LCT\),动态树的一种,又可以 ...
随机推荐
- 命令行启动ubuntu
图形模式下,首先进入终端: 1. 运行 sudo vi/etc/default/grub 2. 找到 GRUB_CMDLINE_LINUX_DEFAULT=”quiet splash” 3.改为 GR ...
- python利用有道翻译实现“语言翻译器”的功能
import urllib.request import urllib.parse import json while True: content = input('请输入需要翻译的内容(退出输入Q) ...
- python的搜索路径与包(package)
python的搜索路径其实是一个列表,它是指导入模块时,python会自动去找搜索这个列表当中的路径,如果路径中存在要导入的模块文件则导入成功,否则导入失败: >>> import ...
- ThinkPHP __PUBLIC__的定义 __ROOT__等 常用 常量的定义
'__TMPL__' => APP_TMPL_PATH, // 项目模板目录 '__ROOT__' => __ROOT__, // 当前网站地址 '__APP__' => __APP ...
- 最小生成树之Prim算法(最原始最详细入门)
//算法6.8 普里姆算法 #include <iostream> using namespace std; typedef char VerTexType; typedef int Ar ...
- Combotree--别样的构建层级json字符串
1.先看效果 2.需要使用层级json格式,如: 3.先不要着急怎么去实现它,先来想想怎么用对象来描述它 4.代码 protected void Page_Load(object sender, Ev ...
- Mongo连接远程数据库
mongo IP+Port CrabyterV5 首先这么操作是基于配置了环境变量的,可以参照http://www.cnblogs.com/daiyonghui/p/5209076.html mong ...
- WebGL画点程序v2
本文程序实现画一个点的任务,如下图.其中,点的位置坐标由Javascript传到着色器程序中,而不是直接给定("硬编码")在顶点着色器中. 整个程序包含两个文件,分别是: 1. H ...
- API接口测试用例编写规则(转载)
API接口测试用例编写规则 (1)必需参数覆盖.对于接口的参数,接口文档一般都会说明哪些儿是必需的,哪儿是非必需的.对于必需的参数,一定要测试传参数和不传参数接口是否报错? (2)必需的参数各种情况覆 ...
- js与Jquery的对比
// document.getElementById("divCommit").style.display="none";// document.g ...