zoukankan      html  css  js  c++  java
  • NOIP的基本模板进阶

            NOIP基本模板进阶


    一.Treap

    支持:

    1. 插入x
    2. 删除x(若有多个相同的数,因只删除一个)
    3. 查询x的排名(排名定义为比当前数小的数的个数+1。若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. x的前驱(前驱定义为小于x,且最大的数)
    6. x的后继(后继定义为大于x,且最小的数)
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    #include<cstdlib>
    using namespace std;
    #define INF 0x7fffffff
    #define N 100010
    int n,tot,root;
    struct Treap
    {
        int l,r,val,len,cnt,siz;
    }a[N];
    int New(int x)
    {
        a[++tot].val=x;
        a[tot].len=rand();
        a[tot].cnt=a[tot].siz=1;
        return tot;
    }
    void Update(int p)
    {
        a[p].siz=a[a[p].l].siz+a[a[p].r].siz+a[p].cnt;
    }
    void Build()
    {
        New(-INF);
        New(INF);
        root=1;
        a[1].r=2;
        Update(root);
    }
    int GetRankByVal(int p,int k)
    {
        if(p==0)
            return 0;
        if(k==a[p].val)
            return a[a[p].l].siz+1;
        else if(k<a[p].val)
            return GetRankByVal(a[p].l,k);
        else 
            return GetRankByVal(a[p].r,k)+a[a[p].l].siz+a[p].cnt;
    }
    int GetValByRank(int p,int rank)
    {
        if(p==0)
            return INF;
        if(a[a[p].l].siz>=rank)
            return GetValByRank(a[p].l,rank);
        else if(a[a[p].l].siz+a[p].cnt>=rank)
            return a[p].val;
        else
            return GetValByRank(a[p].r,rank-a[a[p].l].siz-a[p].cnt);
    }
    void zig(int &p)
    {
        int q=a[p].l;
        a[p].l=a[q].r;
        a[q].r=p;
        p=q;
        Update(a[p].r);
        Update(p);
    }
    void zag(int &p)
    {
        int q=a[p].r;
        a[p].r=a[q].l;
        a[q].l=p;
        p=q;
        Update(a[p].l);
        Update(p);
    }
    void Insert(int &p,int k)
    {
        if(p==0)
        {
            p=New(k);
            return;
        }
        if(k==a[p].val)
        {
            a[p].cnt++;
            Update(p);
            return;
        }
        if(k<a[p].val)
        {
            Insert(a[p].l,k);
            if(a[p].len<a[a[p].l].len)
                zig(p);
        }
        else
        {
            Insert(a[p].r,k);
            if(a[p].len<a[a[p].r].len)
                zag(p);
        }
        Update(p);
    }
    void Remove(int &p,int k)
    {
        if(p==0)
            return;
        if(k==a[p].val)
        {
            if(a[p].cnt>1)
            {
                a[p].cnt--;
                Update(p);
                return;
            }
            if(a[p].l||a[p].r)
            {
                if(a[p].r==0||a[a[p].l].len>a[a[p].r].len)
                {
                    zig(p);
                    Remove(a[p].r,k);
                }
                else
                {
                    zag(p);
                    Remove(a[p].l,k);
                }
                Update(p);
            }
            else
                p=0;
            return;
        }
        if(k<a[p].val)
            Remove(a[p].l,k);
        else
            Remove(a[p].r,k);
        Update(p);
    }
    int GetPre(int k)
    {
        int ans=1;
        int p=root;
        while(p)
        {
            if(k==a[p].val)
            {
                if(a[p].l>0)
                {
                    p=a[p].l;
                    while(a[p].r>0)
                        p=a[p].r;
                    ans=p;
                }
                break;
            }
            if(a[p].val<k&&a[p].val>a[ans].val)
                ans=p;
            if(k<a[p].val)
                p=a[p].l;
            else
                p=a[p].r;
        }
        return a[ans].val;
    }
    int GetNxt(int k)
    {
        int ans=2;
        int p=root;
        while(p)
        {
            if(k==a[p].val)
            {
                if(a[p].r>0)
                {
                    p=a[p].r;
                    while(a[p].l>0)
                        p=a[p].l;
                    ans=p;
                }
                break;
            }
            if(a[p].val>k&&a[p].val<a[ans].val)
                ans=p;
            if(k<a[p].val)
                p=a[p].l;
            else
                p=a[p].r;
        }
        return a[ans].val;
    }
    int main()
    {
        scanf("%d",&n);
        Build();
        while(n--)
        {
            int x,k;
            scanf("%d%d",&k,&x);
            if(k==1)
                Insert(root,x);
            if(k==2)
                Remove(root,x);
            if(k==3)
                printf("%d
    ",GetRankByVal(root,x)-1);
            if(k==4)
                printf("%d
    ",GetValByRank(root,x+1));
            if(k==5)
                printf("%d
    ",GetPre(x));
            if(k==6)
                printf("%d
    ",GetNxt(x));
        }
        return 0;
    }

    二.非旋转Treap

    支持普通Treap操作,区间翻转

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    #define N 100010
    int n,tot,root,m;
    bool flag[N];
    struct Treap
    {
        int val,len,siz,ch[2];
        void clear()
        {
            ch[0]=ch[1]=siz=val=len=0;
        }
    }t[N];
    void update(int p)
    {
        t[p].siz=t[t[p].ch[0]].siz+t[t[p].ch[1]].siz+1;
    }
    void pushdown(int p)
    {
        if(!flag[p]) return;
        swap(t[p].ch[0],t[p].ch[1]);
        if(t[p].ch[0]!=0)
            flag[t[p].ch[0]]^=1;
        if(t[p].ch[1]!=0)
            flag[t[p].ch[1]]^=1;
        flag[p]=0;
    }
    int merge(int x,int y)
    {
        if(!x||!y)
            return x+y;
        pushdown(x); pushdown(y);
        if(t[x].len<t[y].len)
        {
            t[x].ch[1]=merge(t[x].ch[1],y);
            update(x);
            return x;
        }
        else
        {
            t[y].ch[0]=merge(x,t[y].ch[0]);
            update(y);
            return y;
        }
    }
    void split_val(int p,int val,int &x,int &y)
    {
        if(!p)
        {
            x=y=0;
            return;
        }
        pushdown(p);
        if(t[p].val<=val)
            x=p,split_val(t[p].ch[1],val,t[p].ch[1],y);
        else
            y=p,split_val(t[p].ch[0],val,x,t[p].ch[0]);
        update(p);
    }
    void split_k(int p,int k,int &x,int &y)
    {
        if(!p)
        {
            x=y=0;
            return;
        }
        pushdown(p);
        if(t[t[p].ch[0]].siz<k)
            x=p,split_k(t[p].ch[1],k-t[t[p].ch[0]].siz-1,t[p].ch[1],y);
        else
            y=p,split_k(t[p].ch[0],k,x,t[p].ch[0]);
        update(p);
    }
    void Insert(int val)
    {
        int a,b;
        t[++tot].len=rand();
        t[tot].val=val;
        t[tot].siz=1;
        split_val(root,val,a,b);
        root=merge(merge(a,tot),b);
    }
    void remove(int val)
    {
        int a,b,c,d;
        split_val(root,val-1,a,b);
        split_k(b,1,c,d);
        t[c].clear();
        root=merge(a,d);
    }
    int getrank(int val)
    {
        int a,b,c;
        split_val(root,val-1,a,b);
        c=t[a].siz+1;
        root=merge(a,b);
        return c;
    }
    int getval(int &p,int k)
    {
        int a,b,c,d,e;
        split_k(p,k-1,a,b);
        split_k(b,1,c,d);
        e=t[c].val;
        p=merge(a,merge(c,d));
        return e;
    }
    int getpre(int x)
    {
        int a,b,c;
        split_val(root,x-1,a,b);
        c=getval(a,t[a].siz);
        root=merge(a,b);
        return c;
    }
    int getnxt(int x)
    {
        int a,b,c;
        split_val(root,x,a,b);
        c=getval(b,1);
        root=merge(a,b);
        return c;
    }
    void coutt(int p)
    {
        if(!p)
            return;
        if(flag[p]!=0)
            pushdown(p);
        coutt(t[p].ch[0]);
        printf("%d ",t[p].val);
        coutt(t[p].ch[1]);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)//普通平衡树
            Insert(i);
        while(m--)
        {
            int l,r,a,b,c;
            scanf("%d%d",&l,&r);
            split_k(root,r,b,c);
            split_k(b,l-1,a,b);
            flag[b]^=1;
            root=merge(a,merge(b,c));
        }
        coutt(root);
        while(n--)//文艺平衡树
        {
            int k,x;
            scanf("%d%d",&k,&x);
            if(k==1)
                Insert(x);
            if(k==2)
                remove(x);
            if(k==3)
                printf("%d
    ",getrank(x));
            if(k==4)
                printf("%d
    ",getval(root,x));
            if(k==5)
                printf("%d
    ",getpre(x));
            if(k==6)
                printf("%d
    ",getnxt(x));
        }
    }

     三.权值线段树

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    #define N 200010
    int m,n,idx,a[N],b[N],cnt[N<<2],u[N],idxx=1;
    void pushup(int p)
    {
        cnt[p]=cnt[p<<1]+cnt[p<<1|1];
    }
    void update(int l,int r,int k,int v)
    {
        if(l==r)
        {
            cnt[k]++;
            return;
        }
        int mid=(l+r)>>1;
        if(v<=mid)
            update(l,mid,k<<1,v);
        if(v>mid)
            update(mid+1,r,k<<1|1,v);
        pushup(k);
    }
    int query(int l,int r,int k,int rank)
    {
        if(l==r)
            return l;
        int mid=(l+r)>>1;
        if(rank<=cnt[k<<1])
            return query(l,mid,k<<1,rank);
        else
            return query(mid+1,r,k<<1|1,rank-cnt[k<<1]);
    }
    int main()
    {
        scanf("%d%d",&m,&n);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&a[i]);
            b[i]=a[i];
        }
        for(int i=1;i<=n;i++)
            scanf("%d",&u[i]);
        sort(b+1,b+m+1);
        int tot=unique(b+1,b+m+1)-b-1;
        for(int i=1;i<=m;i++)
        {
            int x=lower_bound(b+1,b+tot+1,a[i])-b;
            update(1,tot,1,x);
            while(i==u[idxx])
            {
                printf("%d
    ",b[query(1,tot,1,++idx)]);
                ++idxx;
            }
        }
        return 0;
    }
  • 相关阅读:
    Matlab随笔之三维图形绘制
    Matlab随笔之模拟退火算法
    Matlab随笔之矩阵入门知识
    Matlab随笔之求解线性方程
    Matlab随笔之分段线性函数化为线性规划
    Matlab随笔之指派问题的整数规划
    Matlab随笔之线性规划
    Android单位转换 (px、dp、sp之间的转换工具类)
    Android禁止输入表情符号
    设计模式之策略模式
  • 原文地址:https://www.cnblogs.com/jiangminghong/p/10049940.html
Copyright © 2011-2022 走看看