模板题 Problem I Link Cut Tree
@(XSY)[LCT]
Description
你们这么轻松A了前两题,要是AK了我可就惨了,所以这道题一定要是难(shui)题。那出什么难题呢?有了,这样吧,第一题是数,第二题是树,那我就出个同时含有数和树的题不就好了(废话,什么题没有数)。好,那就好办了。看,这里有一个n个节点且节点带权的树,然后我会要你去执行一些操作,处理一些询问。操作和询问有以下4种: 1、‘1 x y’表示将节点x与节点y用一条边相连接,若节点x与节点y本来已经是连通的话,则输出-1表示操作不合法; 2、‘2 x y’表示将当以节点x为根时,节点y与它的父亲节点相连接的边删除,若节点x与节点y本来已经是不连通的话,则输出-1表示操作不合法; 3、‘3 w x y’表示将节点x到节点y路径上的所有点点权加上w,若节点x与节点y本来已经是不连通的话,则输出-1表示操作不合法; 4、‘4 x y’表示请你输出节点x到节点y路径上的所有点中最大的点权,若节点x与节点y本来已经是不连通的话,则输出-1表示操作不合法。 终于有道比较难的题了,这下你们应该不能在1个小时内做出来了吧。什么,你们还有3个小时……
Input
第一行一个整数n表示树的节点个数。 接下来n-1行每行两个整数x、y,表示初始状态节点x与节点y间有一条边。 接下来一行n个整数,第i个数表示节点i的初始点权。 接下来一行一个整数m,表示操作数。 接下来m行,每行以‘1 x y’或‘2 x y’ 或‘3 w x y’ 或‘4 x y’的形式描述操作与询问。
Output
对于每个合法询问,输出一行一个整数表示最大点权。 对于每个非法询问或操作,输出一行一个整数-1表示非法。
Sample Input
5
1 2
2 4
2 5
1 3
1 2 3 4 5
6
4 2 3
2 1 2
4 2 3
1 3 5
3 2 1 4
4 1 4
Sample Output
3
-1
7
HINT
对于50%的数据:1<=n,m<=1000。 对于100%的数据:1<=n,m<=3*10^5,0<=初始点权,w<=3000。
Solution
终于写了一次真的LCT...以前写的都是假的, 时间复杂度根本就不对...
这一题是极好的模板题, 既有update操作, 也有pushdown操作. pushdown操作只有在splay之前才需要, 而update操作则要特别注意, 要用到的地方包括: splay中的rotate, access操作和cut操作. 总而言之, 就是只要是修改到了辅助树中一个点的儿子节点, 就要对其本身进行update.
#include <cstdio>
#include <cctype>
#include <algorithm>
namespace Zeonfai
{
inline int getInt()
{
int a = 0, sgn = 1;
char c;
while(! isdigit(c = getchar()))
if(c == '-')
sgn *= -1;
while(isdigit(c))
a = a * 10 + c - '0', c = getchar();
return a * sgn;
}
}
struct linkCutTree
{
struct node
{
node *pre, *suc[2];
int isRoot, rev;
struct data
{
int w, mx, tag;
inline void add(int a)
{
w += a, mx += a, tag += a;
}
}infr;
inline node()
{
pre = suc[0] = suc[1] = NULL;
isRoot = 1, rev = 0;
infr.w = infr.mx = infr.tag = 0;
}
inline int getRelation()
{
if(pre == NULL)
return -1;
return this == pre->suc[1];
}
inline void pushdown()
{
if(! isRoot)
pre->pushdown();
if(rev)
reverse();
if(suc[0] != NULL)
suc[0]->infr.add(infr.tag);
if(suc[1] != NULL)
suc[1]->infr.add(infr.tag);
infr.tag = 0;
}
inline void update()
{
infr.mx = infr.w;
if(suc[0] != NULL)
infr.mx = std::max(infr.mx, suc[0]->infr.mx);
if(suc[1] != NULL)
infr.mx = std::max(infr.mx, suc[1]->infr.mx);
}
inline void reverse()
{
std::swap(suc[0], suc[1]);
rev ^= 1;
if(suc[0] != NULL)
suc[0]->rev ^= 1;
if(suc[1] != NULL)
suc[1]->rev ^= 1;
}
};
node *nd;
inline void init(int n)
{
nd = new node[n];
}
inline void rotate(node *u)
{
node *pre = u->pre, *prepre = pre->pre;
int k = u->getRelation();
if(u->suc[k ^ 1] != NULL)
u->suc[k ^ 1]->pre = pre;
pre->suc[k] = u->suc[k ^ 1];
u->suc[k ^ 1] = pre;
u->pre = prepre;
if(pre->isRoot)
pre->isRoot = 0, u->isRoot = 1;
else
prepre->suc[pre->getRelation()] = u;
pre->pre = u;
pre->update(), u->update();
}
inline void splay(node *u)
{
u->pushdown();
while(! u->isRoot)
{
if(! u->pre->isRoot)
rotate(u->pre->getRelation() == u->getRelation() ? u->pre : u);
rotate(u);
}
}
inline void access(node *u)
{
splay(u);
if(u->suc[1] != NULL)
u->suc[1]->isRoot = 1, u->suc[1] = NULL, u->update();
while(u->pre != NULL)
{
node *pre = u->pre;
splay(pre);
if(pre->suc[1] != NULL)
pre->suc[1]->isRoot = 1;
pre->suc[1] = u;
u->isRoot = 0;
u->update();
splay(u);
}
}
inline void makeRoot(node *u)
{
access(u);
u->rev ^= 1;
}
inline node* findRoot(node *u)
{
access(u);
while(u->suc[0] != NULL)
u = u->suc[0];
access(u); //find root完一定要access一下啊
return u;
}
inline void cut(node *u, node *v)
{
makeRoot(u);
access(v);
access(v);
v->suc[0]->isRoot = 1, v->suc[0]->pre = NULL, v->suc[0] = NULL;
v->update();
}
inline void link(node *u, node *v)
{
makeRoot(u);
access(v);
access(v);
u->pre = v;
access(u);
}
inline void modify(node *u, node *v, int a)
{
makeRoot(u);
access(v);
access(v);
v->infr.add(a);
}
inline int query(node *u, node *v)
{
makeRoot(u);
access(v);
access(v);
return v->infr.mx;
}
}org;
int main()
{
#ifndef ONLINE_JUDGE
freopen("LCT.in", "r", stdin);
freopen("LCT.out", "w", stdout);
#endif
using namespace Zeonfai;
int n = getInt();
org.init(n + 1);
static int *tmp = new int[n << 1];
for(int i = 2; i < n << 1; i += 2)
tmp[i - 1] = getInt(), tmp[i] = getInt();
for(int i = 1; i <= n; ++ i)
org.nd[i].infr.add(getInt());
for(int i = 2; i < n << 1; i += 2)
org.link(org.nd + tmp[i - 1], org.nd + tmp[i]);
delete[] tmp;
int m = getInt();
for(int i = 0; i < m; ++ i)
{
int opt = getInt(), u = getInt(), v = getInt();
if(opt == 1)
{
org.makeRoot(org.nd + u);
if(org.findRoot(org.nd + v) == org.nd + u)
puts("-1");
else
org.link(org.nd + u, org.nd + v);
}
else if(opt == 2)
{
org.makeRoot(org.nd + u);
if(org.findRoot(org.nd + v) != org.nd + u)
puts("-1");
else
org.cut(org.nd + u, org.nd + v);
}
else if(opt == 3)
{
int tmp = getInt();
org.makeRoot(org.nd + v);
if(org.findRoot(org.nd + tmp) != org.nd + v)
puts("-1");
else
org.modify(org.nd + v, org.nd + tmp, u);
}
else if(opt == 4)
{
org.makeRoot(org.nd + u);
if(org.findRoot(org.nd + v) != org.nd + u)
puts("-1");
else
printf("%d\n", org.query(org.nd + u, org.nd + v));
}
}
}
模板题 Problem I Link Cut Tree的更多相关文章
- 【刷题】洛谷 P3690 【模板】Link Cut Tree (动态树)
题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor ...
- Codeforces Round #339 (Div. 2) A. Link/Cut Tree 水题
A. Link/Cut Tree 题目连接: http://www.codeforces.com/contest/614/problem/A Description Programmer Rostis ...
- LCT总结——概念篇+洛谷P3690[模板]Link Cut Tree(动态树)(LCT,Splay)
为了优化体验(其实是强迫症),蒟蒻把总结拆成了两篇,方便不同学习阶段的Dalao们切换. LCT总结--应用篇戳这里 概念.性质简述 首先介绍一下链剖分的概念(感谢laofu的讲课) 链剖分,是指一类 ...
- LG3690 【模板】Link Cut Tree (动态树)
题意 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代表询问从x到y的路径上的点的权值的xor和.保证x到y是联通的 ...
- 洛谷P3690 [模板] Link Cut Tree [LCT]
题目传送门 Link Cut Tree 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两个整数(x,y),代 ...
- LG3690 【模板】Link Cut Tree 和 SDOI2008 洞穴勘测
UPD:更新了写法. [模板]Link Cut Tree 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 后接两个整数(x,y),代表询问从x到y ...
- LuoguP3690 【模板】Link Cut Tree (动态树) LCT模板
P3690 [模板]Link Cut Tree (动态树) 题目背景 动态树 题目描述 给定n个点以及每个点的权值,要你处理接下来的m个操作.操作有4种.操作从0到3编号.点从1到n编号. 0:后接两 ...
- P3690 【模板】Link Cut Tree (动态树)
P3690 [模板]Link Cut Tree (动态树) 认父不认子的lct 注意:不 要 把 $fa[x]$和$nrt(x)$ 混 在 一 起 ! #include<cstdio> v ...
- AC日记——【模板】Link Cut Tree 洛谷 P3690
[模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...
随机推荐
- Pomodoro APP
2015.5.23 UITableView 的数据源刷新问题 本次发过来的版本五,实现了活动清单列表(AllEventsTableViewController).活动详情(AllEventsViewC ...
- egg.js 学习之 中间件使用
1.在框架和插件中使用中间件 编写中间件 我们先来通过编写一个简单的中间件,来看看中间件的写法. // app/middleware/middlewareOne.js // app/middlewar ...
- (2)zabbix硬件需求
1. 硬件需求 无非就是cpu.内存.硬盘之类的1.1 CPU由你的zabbix数据库使用情况来做决定,如果你监控的项目越多,那你的cpu要越好.具体多好,下面有个表格 1.2 内存与硬盘最基本的需求 ...
- ubuntu下如何对接斗鱼直播
参考教程:https://www.cnblogs.com/liuxuzzz/p/5315998.html 大神写得挺细的,这里都不想再多说了! 为啥要做这个呢?可能真的只是为了好玩吧!!有兴趣直播的孩 ...
- python爬虫(爬取视频)
爬虫爬视频 爬取步骤 第一步:获取视频所在的网页 第二步:F12中找到视频真正所在的链接 第三步:获取链接并转换成机械语言 第四部:保存 保存步骤代码 import re import request ...
- python--基础数据类型的补充与深浅copy
一 . join的用法 lst =['吴彦祖','谢霆锋','刘德华'] s = '_'.join(lst) print(s) # 吴彦祖_谢霆锋_刘德华 # join() "*" ...
- 牛客网暑期ACM多校训练营(第五场) E room(最小费用最大流 , 最小权二分图匹配模板)
链接: https://www.nowcoder.com/acm/contest/143/E 题意: 给定n个宿舍的新安排, 每个宿舍都有4个人, 问要至少有多少个人换位才能变成新安排. 可以建一个二 ...
- Python 前端 Css基础
CSS样式存在的位置 1.放置在标签内,局部生效 <div style="color: red;font-size: 18px;">hello world</di ...
- Mysql 学习目录
Mysql 目录 Mysql之路[第一篇]:Mysql基础 Mysql之路[第二篇]:Mysql 常用命令 Mysql之路[第三篇]:Python对Mysql的操作 Mysql之路[第四篇]:ORM ...
- Core Animation 动画
Core Animation框架 Core Animation可以作用与动画视图或者其他可视元素,为你完成了动画所需的大部分绘帧工作.你只需要配置少量的动画参数(如开始点的位置和结束点的位置)即可使用 ...