HDU4718 The LCIS on the Tree(LCT)
又是一枚LCT,写一发加深一下对LCT的理解。本题的坑爹之处就在于,它实在是太坑爹了。询问的是树路径上的最长连续上升的子串,考验的是怎么样去维护。一开始的想法是维护三个变量 ls,rs,mxl,分别表示左起最长上升,右末最长上升,以及总的最长上升,那么最长上升一定是可以在下面的条件下求到的,
mxl=max(ch[0]->mxl,ch[1]->mxl) 以及
令temp=1 存一下左右区间的左右lval,rval,
if val>ch[0]->rval temp+=ch[0]->rs
if val<ch[1]->lval temp+=ch[1]->ls
但是由于提路径的时候必须要转根,转根的时候区间要有翻转标记,所以要维护信息必须还要知道左起最长下降ld,右末最长下降rd,以及区间总的最长下降mxd.那么每次reverse的时候就可以:
swap(lval,rval) swap(ls,rd) swap(rs,ld) swap(mxl,mxd)。
但是坑爹就在于我们还要特别处理一下各种null,所以本题的坑爹之处很大在于怎么写好这个upd函数。反正我的upd写了100行。。我心都碎了。。。
#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cmath>
#include <cstdio>
#include <algorithm>
using namespace std; #define ll long long
#define maxn 150000
#define INF 1500000000
#define NINF -1 struct Node
{
Node *p, *ch[2];
bool rev;
int val,size;
int lval, rval;
int ls, rs, mxl;
int ld, rd, mxd;
bool isRoot;
Node *fa;
Node(){
val = 0;
size = 0;
ls = rs = mxl = 0;
ld = rd = mxd = 0;
lval = INF; rval = NINF;
isRoot = 0;
}
void setc(Node *c, int d){
ch[d] = c;
c->p = this;
}
bool d(){
return p->ch[1] == this;
}
void upd();
void relax();
void revIt();
void setRoot(Node *f);
}Tnull,*null=&Tnull; void Node::upd(){
size = ch[0]->size + ch[1]->size + 1;
lval = ch[0] != null ? ch[0]->lval : val;
rval = ch[1] != null ? ch[1]->rval : val; if (ch[0] == null){
if (ch[1] == null) ls = ld = 1;
else{
ls = 1; ld = 1;
if (val < ch[1]->lval) ls += ch[1]->ls;
if (val > ch[1]->lval) ld += ch[1]->ld;
}
}
else{
if (ch[0]->ls == ch[0]->size){
ls = ch[0]->size;
if (ch[0]->rval < val){
ls += 1;
if (val < ch[1]->lval){
ls += ch[1]->ls;
}
}
}
else{
ls = ch[0]->ls;
}
if (ch[0]->ld == ch[0]->size){
ld = ch[0]->size;
if (ch[0]->rval > val){
ld += 1;
if (val > ch[1]->lval){
ld += ch[1]->ld;
}
}
}
else {
ld = ch[0]->ld;
}
} if (ch[1] == null){
if (ch[0] == null) rd = rs = 1;
else{
rd = rs = 1;
if (val > ch[0]->rval) rs += ch[0]->rs;
if (val < ch[0]->rval) rd += ch[0]->rd;
}
}
else{
if (ch[1]->rs == ch[1]->size){
rs = ch[1]->size;
if (val < ch[1]->lval){
rs += 1;
if (val>ch[0]->rval){
rs += ch[0]->rs;
}
}
}
else{
rs = ch[1]->rs;
} if (ch[1]->rd == ch[1]->size){
rd = ch[1]->size;
if (val > ch[1]->lval){
rd += 1;
if (val < ch[0]->rval){
rd += ch[0]->rd;
}
}
}
else{
rd = ch[1]->rd;
}
} mxl = max(ch[0]->mxl, ch[1]->mxl);
mxd = max(ch[0]->mxd, ch[1]->mxd);
int temp = 1;
if (ch[0] != null&&val > ch[0]->rval) temp += ch[0]->rs;
if (ch[1] != null&&val < ch[1]->lval) temp += ch[1]->ls;
mxl = max(mxl, temp); temp = 1;
if (ch[0] != null&&val < ch[0]->rval) temp += ch[0]->rd;
if (ch[1] != null&&val>ch[1]->lval) temp += ch[1]->ld;
mxd = max(mxd, temp); } void Node::revIt(){
swap(ch[0], ch[1]);
swap(lval, rval);
swap(ls, rd);
swap(rs, ld);
swap(mxl, mxd);
rev ^= 1;
} void Node::setRoot(Node *f){
fa = f;
isRoot = true;
p = null;
} void Node::relax(){
if (rev){
for (int i = 0; i < 2; i++){
if (ch[i] != null) ch[i]->revIt();
}
rev = 0;
}
} Node mem[maxn], *C = mem; Node *make(int v){
C->lval = C->rval = C->val = v;
C->ls = C->rs = C->mxl = 1;
C->ld = C->rd = C->mxd = 1;
C->rev = 0;
C->ch[0] = C->ch[1] = null;
C->isRoot = true;
C->p = C->fa = null;
return C++;
} void rot(Node *t){
Node *p = t->p;
p->relax();
t->relax();
bool d = t->d();
p->p->setc(t, p->d());
p->setc(t->ch[!d], d);
t->setc(p, !d);
p->upd();
if (p->isRoot){
p->isRoot = false;
t->isRoot = true;
t->fa = p->fa;
}
} void pushTo(Node *t){
static Node *stk[maxn];
int top = 0;
while (t != null){
stk[top++] = t;
t = t->p;
}
for (int i = top - 1; i >= 0; i--)
stk[i]->relax();
} void splay(Node *u, Node *f = null){
pushTo(u);
while (u->p != f){
if (u->p->p == f)
rot(u);
else u->d() == u->p->d() ? (rot(u->p), rot(u)) : (rot(u), rot(u));
}
u->upd();
} Node *v[maxn];
vector<int> G[maxn];
int n, nQ; int que[maxn], fa[maxn], qh = 0, qt = 0;
int wht[maxn]; void bfs(){
qh = qt = 0;
que[qt++] = 1;
while (qh < qt){
int u = que[qh++]; int e;
for (int i = 0; i < G[u].size(); i++){
e = G[u][i];
if (e != fa[u]){
v[e]->fa = v[u]; que[qt++] = e;
}
}
}
} Node *expose(Node *u){
Node *v;
for (v = null; u != null; v = u, u = u->fa){
splay(u);
u->ch[1]->setRoot(u);
u->setc(v, 1);
v->fa = u;
}
return v;
} void makeRoot(Node *u){
expose(u);
splay(u);
u->revIt();
} int main()
{
int T; cin >> T; int ca = 0;
while (T--){
scanf("%d", &n);
C = mem;
for (int i = 1; i <= n; i++){
scanf("%d", wht + i);
v[i] = make(wht[i]);
G[i].clear();
}
fa[1] = -1; int ti;
for (int i = 2; i <= n; i++){
scanf("%d", &ti);
fa[i] = ti;
G[i].push_back(ti); G[ti].push_back(i);
}
bfs();
scanf("%d", &nQ); int ui, vi;
Node *nu, *nv;
printf("Case #%d:\n", ++ca);
for (int i = 0; i < nQ; i++){
scanf("%d%d", &ui, &vi);
nu = v[ui]; nv = v[vi];
makeRoot(nu);
expose(nv);
splay(nv);
printf("%d\n", nv->mxl);
}
if (T != 0) puts("");
}
return 0;
}
HDU4718 The LCIS on the Tree(LCT)的更多相关文章
- HDU 4718 The LCIS on the Tree (动态树LCT)
The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Oth ...
- H - The LCIS on the Tree HDU - 4718
The LCIS on the Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Oth ...
- HDU 4718 The LCIS on the Tree(树链剖分)
Problem Description For a sequence S1, S2, ... , SN, and a pair of integers (i, j), if 1 <= i < ...
- HDU 5002 Tree LCT 区间更新
Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action?c ...
- hdu5398 GCD Tree(lct)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud GCD Tree Time Limit: 5000/2500 MS (Java/O ...
- BZOJ 3282: Tree( LCT )
LCT.. -------------------------------------------------------------------------------- #include<c ...
- BZOJ 2631: tree( LCT )
LCT...略麻烦... -------------------------------------------------------------------------------- #inclu ...
- [bzoj3282]Tree (lct)
昨天看了一天的lct..当然幸好最后看懂了(也许吧..) 论善良学长的重要性T_T,老司机带带我! 这题主要是删边的时候还要判断一下..蒟蒻一开始天真的以为存在的边才能删结果吃了一发wa... 事实是 ...
- Link-Cut Tree(LCT)&TopTree讲解
前言: Link-Cut Tree简称LCT是解决动态树问题的一种数据结构,可以说是我见过功能最强大的一种树上数据结构了.在此与大家分享一下LCT的学习笔记.提示:前置知识点需要树链剖分和splay. ...
随机推荐
- 在Ubuntu下设置环境变量
在Ubuntu中有如下几个文件可以设置环境变量 /etc/profile:在登录时,操作系统定制用户环境时使用的第一个文件,此文件为系统的每个用户设置环境信息,当用户第一次登录时,该文件被执行. /e ...
- 菜鸟学习Spring——60s让你学会动态代理原理
一.为什么要使用动态代理 当一个对象或多个对象实现了N中方法的时候,由于业务需求需要把这个对象和多个对象的N个方法加入一个共同的方法,比如把所有对象的所有方法加入事务这个时候有三种方法 ...
- hdu 1412 {A} + {B}
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3282 {A} + {B} Description 给你两个集合,要求{A} + {B}.注:同一个集合 ...
- 关于asp.net和iis的进程/线程问题,假如网站有1000个人访问,会产生多少个进程/线程啊
详解 ASP.NET异步 超好的文章
- Android Studio SDK 更新方法
通常情况下,下载Android SDK需要连接谷歌的服务器进行下载,由于国内水深火热的网络,速度基本为0.好在国内也有一个更新的镜像地址.本文章介绍如何在不FQ的情况下,使用国内镜像地址,更新andr ...
- ASP运行流程(主要的类笔记)
个人笔记:参考汤姆大叔的MVC之前那些事系列整理 client端发送页面请求,被IIS的某个进程截获,它根据申请的页面后缀(.aspx)不同,调用不同的页面处理程序(.asp->asp.dll ...
- [网络配置相关]——ifconfig命令、ip命令、route命令
ifconfig命令 1. 查看已被激活的网卡的详细信息 # ifconfig eth0 Link encap:Ethernet HWaddr 00:30:67:F2:10:CF inet addr: ...
- [shell基础]——read命令
read命令:在shell中主要用于读取输入.变量.文本 1. 接受标准输入(键盘)的输入,并将输入的数据赋值给设置的变量 [按回车键——表示输入完毕] [若输入的数据多于设置的变 ...
- MATLAB GUI程序设计中ListBox控件在运行期间消失的原因及解决方法
在运行期间,ListBox控件突然消失,同时给出如下错误提示: Warning: single-selection listbox control requires that Value be an ...
- [转载]poi导出excel,可以自定义保存路径
poi导出excel比js导出excel安全性更好,在使用poi导出excel时,先要导入poi-3.5-FINAL-20090928.jar包到你项目的lib目录下,我这里选择是3.5版的 1.ac ...