Bsoj 1322 【練習試題】第K小數

第K小數
Description
  現在已有N個整數,你有以下三種操作:
1 A:表示加入一個值爲A的整數;
2 B:表示刪除其中值爲B的整數;
3 K:表示輸出這些整數中第K小的數;
Input
第一行,兩個整數N,M,表示最開始有N個整數,總共有M個操作
第二行用空格隔開的N個整數
接下來M行,每行表示一個操作
Output
若干行,一行一個整數,表示所求的第K小的數字
Sample Input
5 5
6 2 7 4 9
1 8
1 6
3 10
2 4
3 3
Sample Output
0
7
Hint
【注意】:如果有多個大小相同的數字,只把他們看做一個數字,如樣例。 若找不到第K小的數,輸出0
【數據範圍】
0<=N<=2,000,000
M<=1,000,000
-1,000,000,000<=每個整數<=1,000,000,000
法一:
裸的Splay:
代碼如下:

#include<iostream>
#include<cstdio>
using namespace std;
struct Tarjan{
    int data;
    int l;
    int r;
    int fa;
    int cnt;
}Tree[3000005];
int Root=0;
int size=0;
void update(int x){
    Tree[x].cnt=1;
    if(Tree[x].l)Tree[x].cnt+=Tree[Tree[x].l].cnt;
    if(Tree[x].r)Tree[x].cnt+=Tree[Tree[x].r].cnt;
}
void Rotate(int x){
    int y=Tree[x].fa;
    int z=Tree[y].fa;
    if(Tree[y].l==x){
        Tree[y].l=Tree[x].r;
        if(Tree[x].r)Tree[Tree[x].r].fa=y;
        if(z){
            if(Tree[z].l==y)Tree[z].l=x;
            if(Tree[z].r==y)Tree[z].r=x;
        }
        Tree[x].fa=z;
        Tree[y].fa=x;
        Tree[x].r=y;
    }
    if(Tree[y].r==x){
        Tree[y].r=Tree[x].l;
        if(Tree[x].l)Tree[Tree[x].l].fa=y;
        if(z){
            if(Tree[z].l==y)Tree[z].l=x;
            if(Tree[z].r==y)Tree[z].r=x;
        }
        Tree[x].fa=z;
        Tree[y].fa=x;
        Tree[x].l=y;
    }
    update(y);
}
void Splay(int x){
    int y;
    int z;
    while(Tree[x].fa){
        y=Tree[x].fa;
        z=Tree[y].fa;
        if(!z){
            Rotate(x);
            break;
        }       
        if((Tree[z].l==y)==(Tree[y].l==x)){
            Rotate(y);Rotate(x);
        }
        else {
            Rotate(x);Rotate(x);
        }
    }
    update(x);
    Root=x;
}
int find(int k){
    int p=Root;
    while(Tree[Tree[p].l].cnt+1!=k){
        if(Tree[Tree[p].l].cnt+1>k){
            p=Tree[p].l;
        }
        else {
            k-=Tree[Tree[p].l].cnt+1;
            p=Tree[p].r;
        }
        if(!p)return 0;
    }
    return p;
}
int Find(int k){
    int p=Root;
    while(p){
        if(Tree[p].data==k)return p;
        if(Tree[p].data>k)p=Tree[p].l;
        else p=Tree[p].r;
    }
    return p;
}
void del(int k){
    int p=Find(k);
    if(!p)return;
    Splay(p);
    if(!Tree[p].l&&!Tree[p].r){
        Root=0;
        return;
    }
    if(!Tree[p].l){
        Tree[Tree[p].r].fa=0;
        Root=Tree[p].r;
        return;
    }
    if(!Tree[p].r){
        Tree[Tree[p].l].fa=0;
        Root=Tree[p].l;
        return;
    }
    int t=Tree[p].l;
    Root=t;
    Tree[t].fa=0;
    while(Tree[t].r){
        t=Tree[t].r;
    }
    Splay(t);
    Tree[Tree[p].r].fa=t;
    Tree[t].r=Tree[p].r;
    update(t);
}
void insert(int data){
        int t=Root;
        int fa=0;
        while(t){
            fa=t;
            if(Tree[t].data==data)return;
            if(Tree[t].data>data)t=Tree[t].l;
            else t=Tree[t].r;
        }
        int q=++size;
        Tree[q].data=data;
        Tree[q].l=0;
        Tree[q].r=0;
        Tree[q].fa=fa;
        Tree[q].cnt=1;
        if(Tree[fa].data>data)Tree[fa].l=q;
        else Tree[fa].r=q;
        Splay(q);
}
int n,m;
int main(){
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        insert(x);
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        if(x==1){
            insert(y);
        }
        if(x==2){
            del(y);
        }
        if(x==3){
            printf("%d\n",Tree[find(y)].data);
        }
    }
    return 0;
}

法二:
由於沒有複雜的操作,
故可用stl;
提供兩份代碼:
tree(可能回編譯錯誤):

#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <functional>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

tree<int,null_mapped_type,less<int>,rb_tree_tag,tree_order_statistics_node_update> t;

int main(){
    int n,m,a,k;
    scanf("%d%d",&n,&m);
    for(int i=0,x;i<n;++i){
        scanf("%d",&x);
        t.insert(x);
    }
    while(m--){
        scanf("%d%d",&a,&k);
        if(a==1)t.insert(k);
        else if(a==2)t.erase(k);
        else printf("%d\n",t.size()<k?0:*t.find_by_order(k-1));
    }
}

set:

#include<iostream>
#include<iomanip>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<set>
using namespace std;
set<int> S;
set<int>::iterator it;
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i=1;i<=n;i++){
        scanf("%d",&x);
        S.insert(x);
    }
    for(int i=1;i<=m;i++){
        scanf("%d%d",&x,&y);
        if(x==1){
            S.insert(y);
        }
        if(x==2){
            it=S.find(y);
            if(it!=S.end()){
                S.erase(it);
            }
        }
        if(x==3){
            for(it=S.begin();it!=S.end();it++){
                y--;
                if(y==0){printf("%d\n",*it);break;}
            }
            if(it==S.end())printf("0\n");
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章