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\),动态树的一种,又可以 ...
随机推荐
- XML案例(简单的考生成绩管理系统)
1.以如下格式的exam.xml文件为例 <?xml version="1.0" encoding="UTF-8" standalone="no ...
- git 设定全局ignore
创建: 2017/08/08 位置: $HOME/.config/git/ignore git/ignore 要自建 内容 https://github.com/github/gitignore ...
- js返回16位随机数
public string GetDataRandom() { string strData=DateTime.Now.ToString(); ...
- APP加固反调试(Anti-debugging)技术点汇总
0x00 时间相关反调试 通过计算某部分代码的执行时间差来判断是否被调试,在Linux内核下可以通过time.gettimeofday,或者直接通过sys call来获取当前时间.另外,还可以通过自定 ...
- MySQL实现递归查询
DROP FUNCTION IF EXISTS queryChildrenCaseInfo;CREATE FUNCTION queryChildrenCaseInfo(cId INT)RETURNS ...
- angualr2之路由与导航(一)
1. 唯一根模块式组件导航 在唯一根模块式组件导航中,全局只有一个模块,即根模块. 1.1 根模块 在根模块中,需要导入所有组件及其对应的服务,并将组件加入声明,将其对应的服务加入提供商. // ap ...
- 水仙花数------"水仙花数 "是指一个三位数,其各位数字立方和等于该数本身。(for循环的嵌套)
package com.zuoye.test;//打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数,//其各位数字立方和等于该数本身.//例如: ...
- ROS:使用ubuntuKylin17.04安装ROS赤xi龟
使用ubuntuKylin17.04安装 参考了此篇文章:SLAM: Ubuntu16.04安装ROS-kinetic 重复官方链接的步骤也没有成功. 此后发现4.10的内核,不能使用Kinetic. ...
- BRAFT EDITOR富文本编辑器
https://braft.margox.cn/demos/basic 官方文档 import React from 'react' import Uploading from '../Upl ...
- vue中用v-for循环出出来的div下面的span不给宽度也能相对于div居中
效果图 1.html <div> <div v-on:mousemove="dataDetails($event, item)" v-on:mouseleave= ...