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\n",GetRankByVal(root,x)-1);
        if(k==4)
            printf("%d\n",GetValByRank(root,x+1));
        if(k==5)
            printf("%d\n",GetPre(x));
        if(k==6)
            printf("%d\n",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\n",getrank(x));
        if(k==4)
            printf("%d\n",getval(root,x));
        if(k==5)
            printf("%d\n",getpre(x));
        if(k==6)
            printf("%d\n",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\n",b[query(1,tot,1,++idx)]);
            ++idxx;
        }
    }
    return 0;
}

 

posted @ 2018-12-01 16:28  jiangminghong  阅读(136)  评论(0编辑  收藏  举报