CF809D Hitchhiking in the Baltic States LIS、平衡树
看到最长上升子序列肯定是DP
设\(f_i\)表示计算到当前,长度为\(i\)的最长上升子序列的最后一项的最小值,显然\(f_i\)是一个单调递增的序列。
转移:对于当前计算的元素\(x\),它的取值范围为\([l,r]\),设当前可以转移的区间为\([j,k]\)(即对于\(\forall p \in [j,k] , f_p \in [l,r)\)且\(f_{j-1} < l , f_{k + 1} \geq r\)),则对于\(\forall p \in [j,k]\)都有\(f_{p + 1} = f_{p} + 1\)(因为序列\(f_i\)是单调递增的,所以转移一定更优)且\(f_j = l\)。
考虑这个转移方程,它的实质就是:删去第\(k+1\)个元素,第\(j\)到\(k\)个元素统一\(+1\),在第\(j\)个元素的左边插入一个值为\(l\)的元素。其实就是平衡树的基本操作,使用平衡树维护即可。
还有我也不知道我的Splay为什么每一次要随机一个点Splay到根才能过……
#include<bits/stdc++.h>
#define MAXN 300010
#define inf 0x7fffffff
using namespace std;
struct node{
int ch[2] , fa , num , add;
}Tree[MAXN];
int cntNode = 2 , N , root = 1;
inline bool son(int dir){
return Tree[Tree[dir].fa].ch[1] == dir;
}
inline void ZigZag(int dir){
bool f = son(dir);
if(Tree[dir].fa == root)
root = dir;
Tree[Tree[dir].fa].ch[f] = Tree[dir].ch[f ^ 1];
Tree[Tree[dir].ch[f ^ 1]].fa = Tree[dir].fa;
int x = Tree[Tree[dir].fa].fa;
Tree[x].ch[son(Tree[dir].fa)] = dir;
Tree[Tree[dir].fa].fa = dir;
Tree[dir].ch[f ^ 1] = Tree[dir].fa;
Tree[dir].fa = x;
}
inline void pushdown(int dir){
if(Tree[dir].add){
Tree[Tree[dir].ch[0]].add += Tree[dir].add;
Tree[Tree[dir].ch[1]].add += Tree[dir].add;
Tree[Tree[dir].ch[0]].num += Tree[dir].add;
Tree[Tree[dir].ch[1]].num += Tree[dir].add;
Tree[dir].add = 0;
}
}
inline void Splay(int dir , int fa){
pushdown(dir);
while(Tree[dir].fa != fa)
if(Tree[Tree[dir].fa].fa == fa)
ZigZag(dir);
else{
if(son(Tree[dir].fa) == son(dir))
ZigZag(Tree[dir].fa);
else
ZigZag(dir);
ZigZag(dir);
}
}
void insert(int &now , int num , int fa){
if(now == 0){
now = ++cntNode;
Tree[now].num = num;
Tree[now].fa = fa;
Splay(now , 0);
return;
}
pushdown(now);
insert(Tree[now].ch[Tree[now].num < num] , num , now);
}
void getPre(int now , int num , int minN){
if(now == 0){
Splay(minN , 0);
return;
}
pushdown(now);
if(Tree[now].num == num){
int t = Tree[now].ch[0];
while(t){
pushdown(t);
if(Tree[t].num != num)
minN = t;
t = Tree[t].ch[1];
}
Splay(minN , 0);
return;
}
if(Tree[now].num < num)
getPre(Tree[now].ch[1] , num , Tree[now].num > Tree[minN].num ? now : minN);
else
getPre(Tree[now].ch[0] , num , minN);
}
void getNXT(int now , int num , int maxN){
if(now == 0){
Splay(maxN , root);
return;
}
pushdown(now);
if(Tree[now].num == num){
int t = Tree[now].ch[1];
while(t){
pushdown(t);
maxN = t;
t = Tree[t].ch[0];
}
Splay(maxN , root);
return;
}
if(Tree[now].num < num)
getNXT(Tree[now].ch[1] , num , maxN);
else
getNXT(Tree[now].ch[0] , num , Tree[now].num < Tree[maxN].num ? now : maxN);
}
inline void find(int dir){
if(Tree[dir].fa)
find(Tree[dir].fa);
pushdown(dir);
}
int main(){
srand((unsigned)time(0));
int ans = 0;
scanf("%d" , &N);
Tree[1].ch[1] = 2;
Tree[2].num = inf;
Tree[2].fa = 1;
for(int i = 1 ; i <= N ; i++){
int a , b;
scanf("%d%d" , &a , &b);
getPre(root , a , 1);
getNXT(root , b - 1 , 2);
Tree[Tree[Tree[root].ch[1]].ch[0]].add++;
Tree[Tree[Tree[root].ch[1]].ch[0]].num++;
if(Tree[Tree[root].ch[1]].ch[1]){
ZigZag(Tree[root].ch[1]);
getNXT(Tree[root].ch[1] , Tree[root].num , 2);
Tree[Tree[root].ch[1]].ch[0] = Tree[root].ch[0];
root = Tree[root].ch[1];
Tree[Tree[root].ch[0]].fa = root;
Tree[root].fa = 0;
}
else
ans++;
insert(Tree[root].ch[Tree[root].num < a] , a , root);
int t = rand() % (i + 2) + 1;
find(t);
Splay(t , 0);
}
cout << ans;
return 0;
}
CF809D Hitchhiking in the Baltic States LIS、平衡树的更多相关文章
- CF809D Hitchhiking in the Baltic States
CF809D Hitchhiking in the Baltic States CF809D 长度为n的序列{xi},n<=3e5,范围在(li,ri)之间,求LIS最长是多长g(i,l)表示前 ...
- 【CF809D】Hitchhiking in the Baltic States Splay
[CF809D]Hitchhiking in the Baltic States 题意:给你n个区间[li,ri],让你选出从中一个子序列,然后在子序列的每个区间里都选择一个tj,满足$t_1< ...
- 【CF809D】Hitchhiking in the Baltic States(Splay,动态规划)
[CF809D]Hitchhiking in the Baltic States(Splay,动态规划) 题面 CF 洛谷 题解 朴素\(dp\):设\(f[i][j]\)表示当前考虑到第\(i\)个 ...
- 【CF809D】Hitchhiking in the Baltic States
题意: 给你n个区间[li,ri],让你选出从中一个子序列,然后在子序列的每个区间里都选择一个tj,满足t1<t2<...<tlent1<t2<...<tlen.最 ...
- CF 809 D Hitchhiking in the Baltic States —— 思路+DP(LIS)+splay优化
题目:http://codeforces.com/contest/809/problem/D 看题解,抄标程...发现自己连 splay 都快不会写了... 首先,题目就是要得到一个 LIS: 但与一 ...
- Codeforces 809D. Hitchhiking in the Baltic States
Description 给出 \(n\) 个数 \(a_i\),每一个数有一个取值 \([l_i,r_i]\) ,你来确定每一个数,使得 \(LIS\) 最大 题面 Solution 按照平时做法,设 ...
- CodeForces 809D Hitchhiking in the Baltic States(FHQ-Treap)
题意 给你长度为$n$的序列,序列中的每个元素$i$有一个区间限制$[l_i,r_i]$,你从中选出一个子序列,并给它们标号$x_i$,要求满足 $,∀i<j,x_i<x_j$,且$, ∀ ...
- CF 809D Hitchhiking in the Baltic States——splay+dp
题目:http://codeforces.com/contest/809/problem/D 如果值是固定的,新加入一个值,可以让第一个值大于它的那个长度的值等于它. 如今值是一段区间,就对区间内的d ...
- Noip前的大抱佛脚----赛前任务
赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...
随机推荐
- Loadrunner 脚本开发-利用Loadrunner生成Web service测试脚本
脚本开发-利用Loadrunner生成Web service测试脚本 1.选择协议--Web Service,如下图 2.导入服务 入口1:点击Manage Services ->弹出窗中选择“ ...
- 微信小程序开发--路由切换,页面重定向
这段时间开发了一个微信小程序,虽然小程序的导航API 官方文档写得很详细,但是在具体开发过程中还是会遇到很多不明白,或者一时转不过弯的地方. 1.页面切换传参,参数读取 1.1 wx.navigat ...
- JavaScript大杂烩10 - 理解DOM
操作DOM 终于到了JavaScript最为核心的部分了,通常来说,操作DOM,为页面提供更为友好的行为是JavaScript根本目标. DOM树 - HTML结构的抽象 既然DOM是操纵HTML ...
- 心迹 使用说明&功能展示
下载地址 心迹.apk 更新于2018.8.9 11:47 测试账号:用户名testing,密码testing 项目地址 GitHub 注册&登录 第一次使用心迹app时,必须进行注册,以便区 ...
- python redis 终端 redis-cli.py mini版本 redis 终端管理工具
Python redis-cli.py Python3 redis-cli 命令行管理工具 redis终端工具 由于最近测试redis未授权访问漏洞,发现本机没有安装redis,不能运行redis-c ...
- Fiddler查看接口响应时间
有时候,某些接口访问过慢,我们需要测试接口查看响应时间,从而进行优化.(由于fiddler自带的没有进行响应时间的统计,所以我们需要给他添加新的规则) 首先打开Fiddler,在菜单栏上面找到Rule ...
- python第五十九天-----补上笔记
rabbitmq_server_topic topic模式 #!/usr/bin/env python #{data} {time} #_*_coding:utf-8_*_ import pik ...
- JRE、JDK概述
JRE(java Runtime Environment java运行环境) 包括java虚拟机(JVM Java Virtual Machine)和Java程序所需的核心类库等, 如果想要运行一个开 ...
- 个人技术博客--团队Git规范(参考西瓜学长)
援引西瓜学长:GitHub团队项目合作流程 废话少说直接写 1.fork 1.对于组员来说第一步就是fork 2.点击fork之后 上面是我们的团队仓库 切换回自己的仓库 就会看到 是fork于团队仓 ...
- 玩转FusionCharts:Y轴数字形式(如去掉K)
玩转FusionCharts:Y轴数字形式(如去掉K) 如果运行FusionCharts带的例子,你会发现FusionCharts表中的数字(通常是Y轴)会带上’k’,也就是如20000,会变成20k ...