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


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

    如果值是固定的,新加入一个值,可以让第一个值大于它的那个长度的值等于它。

    如今值是一段区间,就对区间内的dp值都有影响;中间的那些的值变成了上一个的值+1,左边 l 处多了一个点,右边第一个大于等于 r 的点被删掉。

    用 splay 维护这些点;点的个数就是最多能达到的长度。

    又好好学习了一番 splay 。带有标记的原来是要在那个 splay 操作前那样一条链地 pushdown下来呀。

    非常奇怪的是按题解写法,找第一个小于边界的值,再找右边界那个值的 nxt ,就没问题;而自己找第一个大于等于的值,就会TLE。那个T的点是所有 l , r 都是 1,1e9 的,也许和这个有关?

    加“哨兵”十分方便。

    别忘了 insert 也要 splay 。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=3e5+5;
    int n,c[N][2],tg[N],val[N],fa[N],ans,rt,tot;
    inline int rdn()
    {
        int ret=0;bool fx=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')fx=0;ch=getchar();}
        while(ch>='0'&&ch<='9') ret=(ret<<3)+(ret<<1)+ch-'0',ch=getchar();
        return fx?ret:-ret;
    }
    inline void rotate(int x,int &k)
    {
        int y=fa[x],z=fa[y];
        if(y==k) k=x;
        else c[z][y==c[z][1]]=x;
        int d=(x==c[y][1]);
        fa[x]=z; fa[c[x][!d]]=y; fa[y]=x;
        c[y][d]=c[x][!d]; c[x][!d]=y;
    }
    inline void down(int cr)
    {
        if(!tg[cr])return;
        int ls=c[cr][0],rs=c[cr][1];
        if(ls) tg[ls]+=tg[cr],val[ls]+=tg[cr];
        if(rs) tg[rs]+=tg[cr],val[rs]+=tg[cr];
        tg[cr]=0;
    }
    inline void push(int cr)
    {
        if(fa[cr]) push(fa[cr]);
        down(cr);
    }
    inline void splay(int x,int &k)
    {
        push(x);
        while(x!=k)
        {
            int y=fa[x],z=fa[y];
            if(y!=k)
            {
                if((x==c[y][0])^(y==c[z][0]))
                    rotate(x,k);
                else rotate(y,k);
            }
            rotate(x,k);
        }
    }
    inline int lower(int x)
    {
        int cr=rt,ret=0;
        while(cr)
        {
            down(cr);
            if(val[cr]<x)
                ret=cr,cr=c[cr][1];
            else cr=c[cr][0];
            
    //        if(val[cr]>=x)
    //            ret=cr,cr=c[cr][0];
    //        else cr=c[cr][1];
        }
        return ret;
    }
    inline void del(int cr)
    {
        splay(cr,rt);
        int pr=c[cr][0],nt=c[cr][1];
        while(c[pr][1])pr=c[pr][1];
        while(c[nt][0])nt=c[nt][0];
        splay(pr,rt); splay(nt,c[rt][1]);
        fa[cr]=0; c[nt][0]=0;
    }
    inline void insert(int &cr,int p,int pr)//&
    {
        if(!cr){fa[cr=++tot]=pr;val[cr]=p;splay(cr,rt);return;}//
        down(cr);
        insert(c[cr][val[cr]<p],p,cr);
    }
    int nxt(int x)
    {
        splay(x,rt);//
        int cr=c[x][1];
        while(c[cr][0])cr=c[cr][0];
        return cr;
    }
    inline void solve(int l,int r)
    {
        int x=lower(l),y=lower(r),t=nxt(y);
        if(x!=y)
        {
            splay(x,rt); splay(t,c[rt][1]);
    //        val[x]++;
            tg[c[t][0]]++; val[c[t][0]]++;
        }
    
        if(t!=2) del(t),ans--;
    //    if(y!=2) del(y),ans--;
        insert(rt,l,0); ans++;
    }
    int main()
    {
        n=rdn();
        val[1]=-1e9-5; val[2]=1e9+5;
        fa[2]=1; c[1][1]=2; tot=2; rt=1;
        for(int i=1,l,r;i<=n;i++)
        {
            l=rdn(); r=rdn();
            solve(l,r);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    sqlalchemy 使用pymysql连接mysql 1366错误
    mysql之数据导出
    Go常见语句
    huffman code
    后缀数组,目前比较赶进度,而且有点难,所以放到以后再来看
    hash
    bipartite matching
    spanning tree
    拓扑排序
    Union Find
  • 原文地址:https://www.cnblogs.com/Narh/p/9721058.html
Copyright © 2020-2023  润新知