Vijos 1647 treap

点击打开链接

题意:中文

思路:就是记录哪个用过没用过,然后找第k大,直接用名次树就行了

#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
vector<int>G[maxn*10];
int id[maxn],vis[maxn*10];
inline int getint(){
    int res=0;
    char c=getchar();
    bool mi=false;
    while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
    while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
    return mi ? -res : res;
}
inline ll getll(){
    ll res=0;
    char c=getchar();
    bool mi=false;
    while(c<'0' || c>'9') mi=(c=='-'),c=getchar();
    while('0'<=c && c<='9') res=res*10+c-'0',c=getchar();
    return mi ? -res : res;
}
struct Node{
    Node *ch[2];
    int r,v,s,weight;
    Node(int v):v(v){ch[0]=ch[1]=NULL;r=rand();s=1;weight=1;}
    int cmp(int x){
        if(x==v) return -1;
        return x<v? 0:1;
    }
    void maintain(){
        s=weight;
        if(ch[0]!=NULL) s+=ch[0]->s;
        if(ch[1]!=NULL) s+=ch[1]->s;
    }
};
Node *root;
void Rotate(Node* &o,int d){
    Node* k=o->ch[d^1];o->ch[d^1]=k->ch[d];k->ch[d]=o;
    o->maintain();k->maintain();o=k;
}
void Insert(Node* &o,int x){
    if(o==NULL) o=new Node(x);
    else{
        if(x==o->v) o->weight++;
        else{
            int d=x<(o->v)? 0:1;
            Insert(o->ch[d],x);
            if(o->ch[d]->r>o->r) Rotate(o,d^1);
        }
    }
    o->maintain();
}
void Remove(Node* &o,int x){
    int d=o->cmp(x);
    if(d==-1){
        if(o->weight>1) o->weight--;
        else{
            Node* u=o;
            if(o->ch[0]!=NULL&&o->ch[1]!=NULL){
                int d2=(o->ch[0]->r>o->ch[1]->r?1:0);
                Rotate(o,d2);Remove(o->ch[d2],x);
            }else{
                if(o->ch[0]==NULL) o=o->ch[1];
                else o=o->ch[0];
                delete u;
            }
        }
    }else Remove(o->ch[d],x);
    if(o!=NULL) o->maintain();
}
int Kth(Node* o,int k){
//    if(o==NULL) return inf;
    int s=(o->ch[0]==NULL?0:o->ch[0]->s);
    if(k<s+1) return Kth(o->ch[0],k);
    else if(k>s+o->weight) return Kth(o->ch[1],k-(s+o->weight));
    else return o->v;
}
int get_min(){
    if(root==NULL) return -100000000;
    Node* now=root;
    while(now->ch[0]!=NULL) now=now->ch[0];
    return now->v;
}
int main(){
    int price,x,y,sum1,sum2,sum3;
    memset(vis,0,sizeof(vis));
    scanf("%d",&price);
    root=NULL;
    sum1=sum2=sum3=0;
    while(1){
        x=getint();
        if(x==0) break;
        y=getint();
        if(x==1){
            sum1++;vis[sum1]=1;
            G[y].push_back(sum1);
            Insert(root,y);
        }else if(x==2){
            vis[y]=0;
        }else{
            if(root==NULL||root->s<y) printf("Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!\n");
            else{
                int tmp=Kth(root,root->s-y+1);
                if(tmp>price) printf("Dui bu qi,Mei you.\n");
                else{
                    int flag=0;
                    for(unsigned int i=0;i<G[tmp].size();i++){
                        if(vis[G[tmp][i]]){
                            flag=1;break;
                        }
                    }
                    if(flag) printf("You. %d Yuan.\n",tmp);
                    else printf("Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!\n");
                }
            }
        }
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值