题目:http://codeforces.com/contest/809/problem/D

看题解,抄标程...发现自己连 splay 都快不会写了...

首先,题目就是要得到一个 LIS;

但与一般不同的是,新加入的不是一个值,而是一个取值范围;

仍是设 f[i] 表示长度为 i 的 LIS 的结尾最靠前是哪个位置,而此时新出现一个区间 l~r;

如果 f[i] < l,那么可以接上一个 l 变成 f[i+1],也就是 f[i+1] = l;

如果 l <= f[i] <= r,也可以把这个 f[i] 通过选这个区间里的值而尽量提前,最多能提前到上一个 f[j] , l <= f[j] < f[i] <= r;

也就是此时,f[i] = f[j] + 1;

可以知道上一个位置 j 就是 i-1,也就是新增区间带来了这样的转移:f[i] = min( f[i] , f[i-1] + 1),而 f[i-1] + 1 <= f[i] , 所以 f[i] = f[i-1] + 1;

综上,新增加一个区间:

1.会使 l 左边第一个 f[i] < l 转移到 f[i+1] = l;

2.使区间内部的值都向前跳到上一个的后一个,即 f[i+1] = f[i] + 1 , l <= f[i] < f[i+1] <= r;

3.使右边第一个 f[i] > r 转移到 f[i-1] + 1;

可以发现,转移2可以看做是区间内的 f[] 都向右移动了一下,然后区间左边第一个移动到了左端点,右边第一个移到区间内,同时角标(答案)+1;

就可以用 splay 维护,每次找到值在 l~r 范围内的,+1,再删除……,加入……什么的...

然后就模仿了标程的写法...

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ls c[x][0]
#define rs c[x][1]
using namespace std;
int const xn=3e5+;
int n,Q,v[xn],lzy[xn],fa[xn],c[xn][],rt,ans;
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=(ret<<)+(ret<<)+ch-'',ch=getchar();
return f?ret:-ret;
}
void pushdown(int x)
{
if(!lzy[x])return;
v[ls]+=lzy[x]; lzy[ls]+=lzy[x];
v[rs]+=lzy[x]; lzy[rs]+=lzy[x];
lzy[x]=;
}
void push(int x)
{
if(fa[x])push(fa[x]);
pushdown(x);
}
void rotate(int x)
{
int y=fa[x],z=fa[y],d=(c[y][]==x);
if(z)c[z][c[z][]==y]=x;
fa[x]=z; fa[y]=x; fa[c[x][!d]]=y;
c[y][d]=c[x][!d]; c[x][!d]=y;
}
void splay(int x,int f)
{
push(x);//!
while(fa[x]!=f)
{
int y=fa[x],z=fa[y];
if(z!=f)
{
if((c[y][]==x)^(c[z][]==y))rotate(x);
else rotate(y);
}
rotate(x);
}
if(!f)rt=x;
}
int low(int k)//<=k
{
int nw=rt,ret=;
while(nw)
{
pushdown(nw);//!!!
if(v[nw]<k)ret=nw,nw=c[nw][];
else nw=c[nw][];
}
return ret;
}
int nxt(int x)
{
splay(x,); int nw=c[x][];
while(c[nw][])nw=c[nw][];
return nw;
}
void insert(int &x,int k,int f)
{
if(!x){v[x=++n]=k; fa[x]=f; splay(x,); return;}
pushdown(x);//!!
insert(c[x][k>v[x]],k,x);
}
void del(int x)
{
splay(x,); int p=c[x][],q=c[x][];
while(c[p][])p=c[p][];
while(c[q][])q=c[q][];
splay(p,); splay(q,p);
c[q][]=; fa[x]=;
}
void solve(int l,int r)
{
int p=low(l),q=low(r),t=nxt(q);
if(p!=q)//!
{
splay(p,); splay(t,p);
v[c[t][]]++; lzy[c[t][]]++;
}
if(t!=)del(t),ans--;
insert(p,l,); ans++;
}
int main()
{
Q=rd();
v[++n]=(<<); v[++n]=-(<<); fa[]=; c[][]=; rt=;//
for(int i=,l,r;i<=Q;i++)l=rd(),r=rd(),solve(l,r);
printf("%d\n",ans);
return ;
}

CF 809 D Hitchhiking in the Baltic States —— 思路+DP(LIS)+splay优化的更多相关文章

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

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

  2. 【CF809D】Hitchhiking in the Baltic States Splay

    [CF809D]Hitchhiking in the Baltic States 题意:给你n个区间[li,ri],让你选出从中一个子序列,然后在子序列的每个区间里都选择一个tj,满足$t_1< ...

  3. CF809D Hitchhiking in the Baltic States

    CF809D Hitchhiking in the Baltic States CF809D 长度为n的序列{xi},n<=3e5,范围在(li,ri)之间,求LIS最长是多长g(i,l)表示前 ...

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

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

  5. 【CF809D】Hitchhiking in the Baltic States

    题意: 给你n个区间[li,ri],让你选出从中一个子序列,然后在子序列的每个区间里都选择一个tj,满足t1<t2<...<tlent1<t2<...<tlen.最 ...

  6. CF809D Hitchhiking in the Baltic States LIS、平衡树

    传送门 看到最长上升子序列肯定是DP 设\(f_i\)表示计算到当前,长度为\(i\)的最长上升子序列的最后一项的最小值,显然\(f_i\)是一个单调递增的序列. 转移:对于当前计算的元素\(x\), ...

  7. Codeforces 809D. Hitchhiking in the Baltic States

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

  8. CodeForces 809D Hitchhiking in the Baltic States(FHQ-Treap)

    题意 给你长度为$n$的序列,序列中的每个元素$i$有一个区间限制$[l_i,r_i]$,你从中选出一个子序列,并给它们标号$x_i$,要求满足 $,∀i<j,x_i<x_j$,且$, ∀ ...

  9. E - Emptying the Baltic Kattis - emptyingbaltic (dijkstra堆优化)

    题目链接: E - Emptying the Baltic Kattis - emptyingbaltic 题目大意:n*m的地图, 每个格子有一个海拔高度, 当海拔<0的时候有水. 现在在(x ...

随机推荐

  1. FZU1004-Number Triangle经典动归题,核心思路及代码优化

    Problem 1004 Number Triangle Accept: 2230    Submit: 5895Time Limit: 1000 mSec    Memory Limit : 327 ...

  2. [codeforces538F]A Heap of Heaps

    [codeforces538F]A Heap of Heaps 试题描述 Andrew skipped lessons on the subject 'Algorithms and Data Stru ...

  3. PHP应用日期与时间

    <?php/* 时间戳 * * 1. 是一个整数 * 2. 1970-1-1 到现在的秒数 1213212121 * * 2014-02-14 11:11:11 * * 02/14/2014 1 ...

  4. hdu3622:Bomb Game

    给n<=100对点,从每对点里面挑一个并以这些挑出的点为圆心画圆,并且这些圆不能互相覆盖,找出一种方案使得这些圆半径中最小的那个最大. “最小值最大”就是二分答案啦!考虑现在每个点都画出半径x的 ...

  5. poj 2480 Longge's problem [ 欧拉函数 ]

    传送门 Longge's problem Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7327   Accepted: 2 ...

  6. iOS 用cornerstone 创建分支

    第一步:在cornerstone中添加服务器上的代码路径,如下: 第二步:选中服务器路径下的代码,选择“分支”按钮 第三步:开始创建分支 第四步:效果图如下 第五步:选择分支下的路径下载代码并进行修改 ...

  7. django学习之- Cookie

    cookie:客户端游览器上的一个文件,以键值对进行保存,类似字典{'k':'sfs'},与服务器端没有关系,当游览器访问服务器时候,服务器会生成一个随机字符串保存在cookie中返回给客户端,这样当 ...

  8. 一份关于webpack2和模块打包的新手指南(一)

    webpack已成为现代Web开发中最重要的工具之一.它是一个用于JavaScript的模块打包工具,但是它也可以转换所有的前端资源,例如HTML和CSS,甚至是图片.它可以让你更好地控制应用程序所产 ...

  9. SOJ 4467 easyproblem 2【欧拉函数 最大公因数和】

    这题wa的莫名其妙,郁闷了一下午,队友暴力一发跟我答案也是一样.后来队友说试试把%I64d换成%lld,果然一下ac...(暴露了在soj做题少.. ac之后排在ranklist的最后一名...目前也 ...

  10. HDU 1041

    题意: 给原始序列1 给定变化规则是,对于原来的序列每一个0前边插入1,每个1前边插入0. 问原始序列经过n次变化之后有多少对相邻的0. 规律题: 从第二次开始 当第奇数次变化之后,数量变成原来数量的 ...