Treap 維護集合模板

該集合不允許出現重複元素,支持插入一個元素,刪除一個元素,查詢元素x的排名,以及查詢排名爲x的元素。

Treap.cpp

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=1000000+10;
namespace Treap{
    int ch[maxn][2],k[maxn],r[maxn],siz[maxn],ncnt;
    int Root=0;void init(){Root=0;ncnt=0;}
    int _cmp(int t,int x){
        if(k[t]==x)return -1;
        return x < k[t] ? 0 : 1;
    }
    void maintain(int t){
        siz[t]=siz[ch[t][0]]+siz[ch[t][1]]+1;
    }
    void rotate(int& t,int d){
        int k=ch[t][d^1];
        ch[t][d^1]=ch[k][d];ch[k][d]=t;
        maintain(t);t=k;maintain(k);
    }
    void insert(int& t,int x){
        if(t==0){
            t=++ncnt;ch[t][0]=ch[t][1]=0;
            k[t]=x;r[t]=rand();siz[t]=1;
        }else{
            int d=_cmp(t,x);if(d==-1)return;
            insert(ch[t][d],x);maintain(t);
            if(r[t]<r[ch[t][d]])rotate(t,d^1);
        }
    }
    void erase(int& t,int x){
        if(t==0)return;     int d=_cmp(t,x);
        if(d==-1){
            if(ch[t][0]==0 && ch[t][1]==0)t=0;
            else if(ch[t][0]==0 || ch[t][1]==0)
                t=ch[t][0]+ch[t][1];
            else{
                rotate(t,0);erase(ch[t][0],x);
                maintain(t);
            }
        }else erase(ch[t][d],x),maintain(t);
    }
    int rank(int t,int x){
        if(t==0)return 1;   int d=_cmp(t,x);
        if(d==-1)return siz[ch[t][0]]+1;
        int ans=rank(ch[t][d],x);
        return d==1 ? ans+siz[ch[t][0]]+1 : ans;
    }
    int _comp(int x,int y){
        if(x==y)return -1;
        return x>y ? 0 : 1;
    }
    int xth(int t,int x){
        if(t==0)return x<=0 ? -0x7f7f7f7f : 0x7f7f7f7f;
        int d=_comp(siz[ch[t][0]]+1,x);
        if(d==-1)return k[t];
        if(d== 1)x-=siz[ch[t][0]]+1;
        return xth(ch[t][d],x);
    }
    void insert(int x){     insert(Root,x);}
    void erase (int x){      erase(Root,x);}
    int  rank  (int x){return rank(Root,x);}
    int  xth   (int x){return  xth(Root,x);} 
}
#include<cctype>
int geti(){
    int ans=0;int flag=0;char c=getchar();
    while(!isdigit(c)){flag|=c=='-';c=getchar();}
    while( isdigit(c)){ans=ans*10+c-'0';c=getchar();}
    return flag?-ans:ans;
}
template<class T>inline void puti(T x){
    if(x<0)x=-x,  putchar('-');
    if(x>9)puti(x/10); putchar(x%10+'0');
}
int main(){
    int q=geti();//instructions
    while(q--){
        int op=geti(),x=geti();
             if(op==1)    Treap::insert(x);//insert
        else if(op==2)     Treap::erase(x);//erase
        else if(op==3)puti(Treap::rank(x)),putchar('\n');//rank
        else if(op==4) puti(Treap::xth(x)),putchar('\n');//xth
    }
    return 0;
}

bforce.cpp 暴力程序

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int maxn=1000000+10;bool exist[maxn];
int rank(int x){
    int ans=0;
    for(int i=1;i<x;i++)ans+=exist[i];
    return ans+1;
}
int xth(int x){
    for(int i=1;x;i++){
        x-=exist[i];if(x==0)return i;
    }
}
int main(){
    int q;scanf("%d",&q);
    while(q--){
        int op,x;scanf("%d%d",&op,&x);
             if(op==1)exist[x]=1;
        else if(op==2)exist[x]=0;
        else if(op==3)printf("%d\n",rank(x));
        else if(op==4) printf("%d\n",xth(x));
    }
    return 0;
}

data.cpp 數據生成器

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<ctime>
using namespace std;
int rand(int L,int R){return rand()%(R-L+1)+L;}
bool exist[1000000+10];int cnt=0;
int main(){
    srand(time(NULL));
    int n=rand(50,100);printf("%d\n",n);
    while(cnt<30){
        int x=rand(1,1000);
        if(exist[x])continue;
        exist[x]=1;cnt++;
        printf("1 %d\n",x);
    }
    while(cnt>20){//erase
        for(int j=1;j<=1000 && cnt>20;j++){
            if(exist[j] && (rand()&1)){
                cnt--;exist[j]=0;printf("2 %d\n",j);
            }
        }
    }
    for(int i=41;i<=n;i++){
        int op=rand(3,4);
        if(op==3){
            int x;
            while(1)for(int i=1;i<=1000;i++)
                if(exist[i] && (rand()&1)){
                    x=i;goto outside;
                }
            outside:printf("3 %d\n",x);
        }else if(op==4){
            int x=rand(1,cnt);
            printf("4 %d\n",x);
        }
    }
    return 0;
}

try.bat 對拍程序

@echo off
set /a i=1
:begin
  if %i% GTR 100 goto end
  echo round %i% ...
  data.exe   > input.txt
  treap.exe  < input.txt > output.txt
  bforce.exe < input.txt > std.txt
  fc output.txt std.txt
  if errorlevel 1 pause
  set /a i=i+1
goto begin
:end
echo end!
pause
發佈了71 篇原創文章 · 獲贊 160 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章