又是一枚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)的更多相关文章

  1. 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 ...

  2. 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 ...

  3. 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 < ...

  4. HDU 5002 Tree LCT 区间更新

    Tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action?c ...

  5. hdu5398 GCD Tree(lct)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud GCD Tree Time Limit: 5000/2500 MS (Java/O ...

  6. BZOJ 3282: Tree( LCT )

    LCT.. -------------------------------------------------------------------------------- #include<c ...

  7. BZOJ 2631: tree( LCT )

    LCT...略麻烦... -------------------------------------------------------------------------------- #inclu ...

  8. [bzoj3282]Tree (lct)

    昨天看了一天的lct..当然幸好最后看懂了(也许吧..) 论善良学长的重要性T_T,老司机带带我! 这题主要是删边的时候还要判断一下..蒟蒻一开始天真的以为存在的边才能删结果吃了一发wa... 事实是 ...

  9. Link-Cut Tree(LCT)&TopTree讲解

    前言: Link-Cut Tree简称LCT是解决动态树问题的一种数据结构,可以说是我见过功能最强大的一种树上数据结构了.在此与大家分享一下LCT的学习笔记.提示:前置知识点需要树链剖分和splay. ...

随机推荐

  1. 在WPF中显示GIF图片并实现循环播放

    WPF中有一个MediaElement媒体控件,可以来播放媒体,同时也可以显示GIF图片.但看到网上有些人说用MediaElement不能加载作为资源或内嵌的资源的GIF图片,我猜他们一定是在前台用X ...

  2. oracle 查看隐含参数脚本

    set linesize 132 column name format a30 column value format a25 select x.ksppinm name, y.ksppstvl va ...

  3. Python pexpect出现错误‘module have no attribute "spawn" 解决办法

    今天我遇到了这个错误,现在将错误总结如下: 1.首先查询一下自己的操作系统,pexpect中的spawn()和run()仅仅运行在POSIX系统上,在WINDOWS下是没有这两个东西的,在官网http ...

  4. ANT编译build.xml

    一,体验ant就像每个语言都有HelloWorld一样,一个最简单的应用能让人感受一下Ant1,首先你要知道你要干什么,我现在想做的事情是:编写一些程序编译它们把它打包成jar包把他们放在应该放置的地 ...

  5. Oracle HS (Heterogeneous Services)深入解析 及协同Gateway工作流程(转)

    异构的数据源同Oracle Database做交互原理. 图1 上图是一张Oracle 异构连接处理的架构图,其中我们可以看到主要的非数据源模块包括有HS(Heterogeneous Service) ...

  6. Your First ASP.NET 5 Application on a Mac

    Your First ASP.NET 5 Application on a Mac By Daniel Roth, Steve Smith, Rick Anderson ASP.NET 5 is cr ...

  7. MVC 中如何将带有标签的字符串转换为HTML 标签 显示出来?

    出现问题的现象:

  8. Linux rsync 同步

    rsync 是一个快速增量文件传输工具,它可以用于在同一主机备份内部的备分,我们还可以把它作为不同主机网络备份工具之用.本文主要讲述的是如何自架rsync服务器,以实现文件传输.备份和镜像.相对tar ...

  9. My First Django Project (3) - Apache set up

    Holy moly!!!!因为漏了一下斜杠,害我反复调试了2,3天,无法读取static 文件,一直找不出原因,后来在apache的error.log中发现了原因. 1. 下载了apache 2.4, ...

  10. (转)Unity3D游戏开发 NGUI之渐变加载到100%的Loading场景进度条

    NGUI 现有的进度条存在的问题: 进度条跳跃式前进,加载到90%后卡住,突然进入下一个场景.接下来就是解决这个问题. 背景 通常游戏的主场景包含的资源较多,这会导致加载场景的时间较长.为了避免这个问 ...