CF809D

好神奇的数据结构呀...

首先我们考虑:暴力怎么做?

设状态$dp[j]$表示长度为$j$的序列最后一个数最小是几,如果$j$位置的限制区间为$[l,r]$,那么显然有转移:

$dp[j]=l(dp[j-1]<l)$

$dp[j]=dp[j-1]+1(l\leq dp[j-1]\leq r-1)$

$dp[j]=dp[j] (dp[j-1] \geq r)$

正确性显然

考虑优化:我们考虑上面三个操作的实质:

第一个转移方向:在$l$的前驱后面插入$l$

第二个转移方向:把区间$[l,r-1]$整体加一,之后右移一格(相当于向后转移了一个位置)

第三个转移方向:删去$r$的后继

那么用平衡树直接实现上面三个操作即可,考虑到每次都有插入操作,因此事实上第二个操作不需要真正右移,只需加一即可

强烈建议fhq_treap实现

代码:

#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <ctime>
#define ls tree[rt].lson
#define rs tree[rt].rson
using namespace std;
struct FHQ_TREAP
{
    int lson,rson;
    int siz;
    int val,rank;
    int lazy;
}tree[300005];
int tot=0;
int rot,re,n;
void pushup(int rt)
{
    tree[rt].siz=tree[ls].siz+tree[rs].siz+1;
}
void pushdown(int rt)
{
    if(!rt)return;
    if(ls)tree[ls].lazy+=tree[rt].lazy,tree[ls].val+=tree[rt].lazy;
    if(rs)tree[rs].val+=tree[rt].lazy,tree[rs].lazy+=tree[rt].lazy;
    tree[rt].lazy=0;
}
int new_node(int v)
{
    int ret=++tot;
    tree[ret].siz=1,tree[ret].val=v,tree[ret].rank=rand();
    return ret;
}
int merge(int x,int y)
{
    if((!x)||(!y))return x|y;
    if(tree[x].lazy)pushdown(x);
    if(tree[y].lazy)pushdown(y);
    if(tree[x].rank<tree[y].rank)
    {
        tree[x].rson=merge(tree[x].rson,y);
        pushup(x);
        return x;
    }else
    {
        tree[y].lson=merge(x,tree[y].lson);
        pushup(y);
        return y;
    }
}
void split(int rt,int k,int &x,int &y)
{
    if(!rt){x=y=0;return;}
    if(tree[rt].lazy)pushdown(rt);
    if(tree[rt].val<=k)x=rt,split(rs,k,rs,y);
    else y=rt,split(ls,k,x,ls);
    pushup(rt);
}
void ins(int v)
{
    int x,y;
    split(rot,v,x,y);
    rot=merge(merge(x,new_node(v)),y);
}
void del(int v)
{
    int x,y,z,w;
    split(rot,v,x,y);
    split(x,v-1,z,w);
    w=merge(tree[w].lson,tree[w].rson);
    rot=merge(merge(z,w),y);
}
void update(int rt,int l,int r)
{
    int x,y,z,w;
    split(rot,l-1,x,y);
    split(y,r,z,w);
    if(z)tree[z].lazy++,tree[z].val++;
    rot=merge(x,merge(z,w));
}
void get_pro(int rt,int v)
{
    if(!rt)return;
    if(v<=tree[rt].val)get_pro(ls,v);
    else re=tree[rt].val,get_pro(rs,v);
}
int get_minn(int rt)
{
    if(!ls)return tree[rt].val;
    else return get_minn(ls);
}
int get_sub(int v)
{
    int x,y;
    split(rot,v,x,y);
    int ret=get_minn(y);
    rot=merge(x,y);
    return ret;
}
inline int read()
{
    int f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
void solve()
{
    srand(time(NULL));
    n=read();
    for(int i=1;i<=n;i++)
    {
        int l=read(),r=read();
        if(i==1){ins(l);continue;}
        re=get_sub(r-1);
        update(rot,l,r-1);
        if(re)del(re);
        ins(l);
    }
    if(!rot)printf("0\n");
    else printf("%d\n",tree[rot].siz);
}
int main()
{
    solve();
    return 0;
}

 

posted @ 2019-06-28 10:08  lleozhang  Views(196)  Comments(0Edit  收藏  举报
levels of contents