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\),动态树的一种,又可以 ...
随机推荐
- Oracle_备份整库
@echo off color 0b & cls echo echo 设置备份文件存放文件夹... echo set "tbuf=C:\OracleBackup" if n ...
- EditPlus 2:用空格替换制表符
打开软件点击菜单栏上的Tools(工具),在点击perferences(外观),再点击左边栏的File->Setting & Syntax(文件->设置与符号),再点击右栏的Tab ...
- LeetCode Weekly Contest 28
1. 551. Student Attendance Record I 2. 552. Student Attendance Record II hihocode原题,https://hihocode ...
- ABP的一些特性 (Attribute)
大家应该很熟悉Attribute这个东西吧,ABP里面扩展了一些特性,做过滤权限,返回内容等进行控制,在这里小记下,方便后续查看. [DontWrapResult] //ABP默认对返回结果做了封装 ...
- Obsolete---标记方法 类过期
最近做一个接口的修改,由于是很老的接口,不太了解外部有多少地方引用了它. 但是内部的方法由于业务发展已经不太适合现在的需求,想改又不该动.所以想到了如果设置为过期. Obsolete 属性将某个程序实 ...
- informix 通过ADO或ODBC连接提取数据时出现中文乱码的解决方法
最近在做一个项目,是对INFORMIX数据库的数据进行大数据分析,INFORMIX数据库数据有上亿条,没有linux的Root权限和informix数据的生产权限,只能读取.客户要求结果显示在内网wi ...
- Power BI 入门资料
1.官方文档 Power BI Desktop:https://docs.microsoft.com/zh-cn/power-bi/desktop-getting-started Power BI 报 ...
- java ---书写自己的名字
public class hello { public static void main(String[] args) { // TODO 自动生成的方法存根 System.out.println(& ...
- vs2015网站部署到iis后运行调试:无法在web服务器上启动调试的问题,403已禁止
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Temporary ASP.NET Files C:\Windows\Microsoft.NET\Frame ...
- 用SQL Server查询所有数据并显示
利用SQL Server查询数据,并把所有数据显示在页面上. "%> <%@page import="jdbc.sqlServer"%> <%@p ...