题意

给你长度为$n$的序列,序列中的每个元素$i$有一个区间限制$[l_i,r_i]$,你从中选出一个子序列,并给它们标号$x_i$,要求满足 $,∀i<j,x_i<x_j$,且$, ∀i,x_i∈[l_i,r_i]$。 问满足条件子序列的长度最长为多少?

其中$1\leq n\leq3\times 10^5\ 1\leq l_i\leq r_i\leq 10^9$

题解

不妨设$f[i][j]$表示已经选到第$i$个,其中最大值为$j$最多能选几个。

显然是开不下的...但是还记得$O(nlogn)$的$LIS$吗?它利用了二分栈!

所以我们不妨考虑设$f[i][j]$表示当前选到第$i$个,已经选了$j$个的末尾最小元素。

如果不选,显然$f[i+1][j]=f[i][j]$

如果$r[i+1]>f[i][j]$,那么,则有$f[i+1][j+1]=max(f[i][j]+1,l[i+1])$

不难发现可以用滚动数组滚掉第一维,所以第一个方程直接作废:

$ f[j+1]=max(f[j]+1,l[i+1]) $

但是时间还是$O(n^2)$的啊,枚举一个$i$,枚举一个$j$。

不急,咱们分开考虑,对于一个$l[i]<f<r[i]$

它的当前$dp$值可以直接$+1$,那么位置也将$+1$因为多选了一个嘛。

剩下的话,就是$f<l[i]$的情况,直接就等于$l[i]$了。

用一颗$FHQ-Treap$维护一下就行了。

$PS$:注意数组开两倍(最开始$n$个以及$dp$中的$n$个新节点)

#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm> template<typename T>
void read(T &x) {
int flag = 1; x = 0; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') flag = -flag; ch = getchar(); }
while(ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= flag;
} const int N = 6e5 + 10, Inf = 1e9 + 7;
int n, l, r;
int rt, tot, val[N], add[N], lc[N], rc[N], pri[N]; inline int node(int x) { val[++tot] = x, pri[tot] = rand(); return tot; }
inline void pushdown(int o) {
if(add[o]) {
val[o] += add[o];
if(lc[o]) add[lc[o]] += add[o];
if(rc[o]) add[rc[o]] += add[o];
add[o] = 0;
}
}
int merge(int l, int r) {
if(!l || !r) return l + r;
pushdown(l), pushdown(r);
if(pri[l] < pri[r]) { rc[l] = merge(rc[l], r); return l; }
else { lc[r] = merge(l, lc[r]); return r; }
}
void split(int o, int k, int &l, int &r) {
if(!o) { l = r = 0; return ; } pushdown(o);
if(val[o] <= k) l = o, split(rc[o], k, rc[o], r);
else r = o, split(lc[o], k, l, lc[o]);
}
int min(int o) { pushdown(o); return lc[o] ? min(lc[o]) : val[o]; }
int calc(int o) {
if(!o) return 0; pushdown(o);
return calc(lc[o]) + calc(rc[o]) + (val[o] < Inf);
} int main () {
read(n), srand(19260817); int x, y, k, p;
for(int i = 1; i <= n; ++i) rt = merge(rt, node(Inf));
for(int i = 1; i <= n; ++i) {
read(l), read(r);
split(rt, l - 1, x, y), split(y, r - 1, k, y);
if(k) ++add[k];
split(y, min(y), p, y);
rt = merge(merge(merge(x, node(l)), k), y);
} printf("%d\n", calc(rt));
return 0;
}

CodeForces 809D Hitchhiking in the Baltic States(FHQ-Treap)的更多相关文章

  1. Codeforces 809D. Hitchhiking in the Baltic States

    Description 给出 \(n\) 个数 \(a_i\),每一个数有一个取值 \([l_i,r_i]\) ,你来确定每一个数,使得 \(LIS\) 最大 题面 Solution 按照平时做法,设 ...

  2. 【CF809D】Hitchhiking in the Baltic States(Splay,动态规划)

    [CF809D]Hitchhiking in the Baltic States(Splay,动态规划) 题面 CF 洛谷 题解 朴素\(dp\):设\(f[i][j]\)表示当前考虑到第\(i\)个 ...

  3. 可持久化treap(FHQ treap)

    FHQ treap 的整理 treap = tree + heap,即同时满足二叉搜索树和堆的性质. 为了使树尽可能的保证两边的大小平衡,所以有一个key值,使他满足堆得性质,来维护树的平衡,key值 ...

  4. BZOJ3159: 决战(FHQ Treap)

    传送门: 解题思路: 算是补坑了,这题除了Invert以外就可以树剖线段树解决了. 考虑Invert操作,延续先前树链剖分的做法,考虑先前算法的瓶颈. 最暴力的方法是暴力交换权值,然而这种方法忽略了当 ...

  5. CF 809D Hitchhiking in the Baltic States——splay+dp

    题目:http://codeforces.com/contest/809/problem/D 如果值是固定的,新加入一个值,可以让第一个值大于它的那个长度的值等于它. 如今值是一段区间,就对区间内的d ...

  6. bzoj千题计划222:bzoj2329: [HNOI2011]括号修复(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2329 需要改变的括号序列一定长这样 :)))((( 最少改变次数= 多余的‘)’/2 [上取整] + ...

  7. bzoj千题计划221:bzoj1500: [NOI2005]维修数列(fhq treap)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1500 1.覆盖标记用INF表示无覆盖标记,要求可能用0覆盖 2.代表空节点的0号节点和首尾的两个虚拟 ...

  8. 洛谷P3391 【模板】文艺平衡树(Splay)(FHQ Treap)

    题目背景 这是一道经典的Splay模板题——文艺平衡树. 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1, ...

  9. LOJ#120. 持久化序列(FHQ Treap)

    题面 传送门 题解 可持久化\(Treap\)搞一搞 //minamoto #include<bits/stdc++.h> #define R register #define inlin ...

随机推荐

  1. jsp05 指令与动作

    JSP7个动作指令如下 : jsp:forward: 执行页面转向,将请求的处理转发到下一个页面. jsp:param: 用于传递参数,必须与其他支持参数曲标签一起使用. jsp:include: 用 ...

  2. 集合框架源码学习之LinkedList

    0-1. 简介 0-2. 内部结构分析 0-3. LinkedList源码分析 0-3-1. 构造方法 0-3-2. 添加add方法 0-3-3. 根据位置取数据的方法 0-3-4. 根据对象得到索引 ...

  3. Python第三方库jieba(中文分词)入门与进阶(官方文档)

    jieba "结巴"中文分词:做最好的 Python 中文分词组件 github:https://github.com/fxsjy/jieba 特点 支持三种分词模式: 精确模式, ...

  4. Python3安装Celery模块后执行Celery命令报错

    1 Python3安装Celery模块后执行Celery命令报错 pip3 install celery # 安装正常,但是执行celery 命令的时候提示没有_ssl模块什么的 手动在Python解 ...

  5. inet_select_addr

    当通过输出设备向目的地址发送报文时,如果没有源地址,则需要调用inet_select_addr来选择ip地址作为源地址: /* 选择ip地址 通过设备找到ip控制块,从ip控制块中遍历地址列表中的主地 ...

  6. DTW 算法(转)

    DTW为(Dynamic Time Warping,动态时间归准)的简称.应用很广,主要是在模板匹配中,比如说用在孤立词语音识别,计算机视觉中的行为识别,信息检索等中.可能大家学过这些类似的课程都看到 ...

  7. linux===Ubuntu修改设备名称

    step1 sudo vim /etc/hostname 修改你需要的,保存退出 step2 sudo vim /etc/hosts 修改你需要的,保存退出 step3 reboot

  8. JAVA 线程状态及转化

    线程状态图 说明:线程共包括以下5种状态.1. 新建状态(New)         : 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread().2. 就绪状 ...

  9. aspxgridview export导出数据,把true显示成‘是’

    项目原因,数据库中的数据是‘true’还有‘false’,但是在页面上要显示为‘是否’,导出来的时候也是要显示成‘是否’ 要在web页面当中显示成‘是否’,只要在gridview的CustomColu ...

  10. [hadoop][会装]zookeeper安装

    1.简介 分布式场景下的各个进程间的协调运作离不开zookeeper, zookeeper已经是大数据领域提供分布式协调服务的事实标准. 本文只介绍zookeeper的安装方法. 2. 节点规划如下: ...