• CF809D Hitchhiking in the Baltic States


    题目描述:

    luogu

    题解:

    平衡树模拟dp?

    设$dp[i]$表示当前状态下长为$i$的合法子序列最后一位的最小值。

    容易发现$dp[i]<dp[i+1]$。

    然后就可以$dp$了。

    (当前可操作区间为$[l,r]$)

    1.$dp[i-1]<l$,有$dp[i]=min(dp[i],l)$。

    此时满足$dp[i-1]<l le dp[i]$。

    2.$l le dp[i-1] < r$,有$dp[i]=min(dp[i],dp[i-1]+1)$,

    其实右边一定最右,因为$dp[i-1]<dp[i]$。

    3.$dp[i-1] ge r$,此时$dp[i]=dp[i]$。

    我们可以用平衡树维护这个转移。

    对于转移1,我们要插入一个$l$。

    对于转移2,我们要将一段区间平移后+1。

    所以,用splay维护插入、区间加法和删除。

    注意三者顺序。

    (splay双旋写成反双旋卡在第80个点卡了半天

    代码:

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    using namespace std;
    const int inf = 0x7f7f7f7f;
    const int N = 500050;
    template<typename T>
    inline void read(T&x)
    {
        T f = 1,c = 0;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
        x = f*c;
    }
    int n;
    struct Splay
    {
        int tot,rt,ch[N][2],fa[N],siz[N];
        int w[N],tag[N];
        Splay()
        {
            tot = 2;rt = 1;
            w[1] = -inf,w[2] = inf;
            fa[2] = 1,ch[1][1] = 2;
            siz[1] = 2,siz[2] = 1;
        }
        void update(int u){siz[u]=siz[ch[u][0]]+siz[ch[u][1]]+1;}
        void add(int u,int k){if(u)w[u]+=k,tag[u]+=k;}
        void pushdown(int u)
        {
            if(tag[u])
            {
                add(ch[u][0],tag[u]);
                add(ch[u][1],tag[u]);
                tag[u]=0;
            }
        }
        int now;
        void rotate(int x)
        {
            int y = fa[x],z = fa[y],k = (ch[y][1]==x);
            ch[z][ch[z][1]==y]=x,fa[x]=z;
            ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y;
            ch[x][!k]=y,fa[y]=x;
            update(y),update(x);
        }
        int sta[N],tl;
        void down(int x)
        {
            sta[tl=1]=x;
            while(fa[x])x=fa[x],sta[++tl]=x;
            while(tl)pushdown(sta[tl--]);
        }
        void splay(int x,int goal)
        {
            down(x);
            while(fa[x]!=goal)
            {
                int y = fa[x],z = fa[y];
                if(z!=goal)
                    (ch[y][1]==x)^(ch[z][1]==y)?rotate(x):rotate(y);
                rotate(x);
            }
            if(!goal)rt=x;
        }
        void get_qq(int u,int k)
        {
            if(!u)return ;pushdown(u);
            if(w[u]<=k)now=u,get_qq(ch[u][1],k);
            else get_qq(ch[u][0],k);
        }
        void get_hj(int u,int k)
        {
            if(!u)return ;pushdown(u);
            if(w[u]>=k)now=u,get_hj(ch[u][0],k);
            else get_hj(ch[u][1],k);
        }
        int qq(int k){get_qq(rt,k);splay(now,0);return now;}
        int hj(int k){get_hj(rt,k);splay(now,0);return now;}
        void work(int l,int r)
        {
            int lp,rp,u;
            
            lp = hj(r);
            if(lp!=2)
            {
                rp = hj(w[lp]+1),lp = qq(w[lp]-1);
                splay(lp,0),splay(rp,lp);
                ch[rp][0]=0;
                update(rp),update(lp);
            }
    
    //        u = qq(inf-1);
    //        splay(u,0);
    
            lp = qq(l-1),rp = hj(r);
            splay(lp,0),splay(rp,lp);
            add(ch[rp][0],1);
    
    //        u = qq(inf-1);
    //        splay(u,0);
    
            rp = hj(w[lp]+1);
            splay(lp,0),splay(rp,lp);
            u = ++tot;w[u]=l;
            siz[u] = 1,fa[u] = rp,ch[rp][0] = u;
            update(rp),update(lp);
    //        splay(u,0);
            
    //        int mid = (2int*l+3int*r)/5;
            u = qq(inf-1);
            splay(u,0);
        }
    }tr;
    int main()
    {
    //    freopen("tt.in","r",stdin);
        read(n);
        for(int l,r,i=1;i<=n;i++)
        {
            read(l),read(r);
            tr.work(l,r);
        }
        printf("%d
    ",tr.siz[tr.rt]-2);
        return 0;
    }
    View Code
  • 相关阅读:
    Mysql的表名/字段名/字段值是否区分大小写
    20个PHP程序性能优化的方法
    PHP中大括号用法
    PHP伪类型和伪变量
    PHP中关于取模运算及符号
    PHP之array_flip()方法
    PHP之implode()方法
    PHP中is_null()方法
    原型模式(Prototype)
    适配器模式
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/11112685.html
Copyright © 2020-2023  润新知