bzoj1503 [ NOI2004 ] --treap

这道题和一般的题目不同,A和S操作要修改所有节点。所以定义基准d,每个节点的工资是它的值+d,这样就能完成所有操作。

I k:将值为k-d的节点插入treap

A k:将d加上k

S k:将d减去k,并将所有值小于min-d的节点删除。

F k:因为treap在插入时就是有序的,所以直接查找。

这里要注意:

在实际编码中,为了减少出错的可能性,一般用一个真实的指针null代替空指针NULL,方法如下:

                            Node *null=new Node();


还有一个略坑的地方就是如果一个员工的初始工资低于工资下界,他将立即离开公司。这不算在离开公司的员工总数内。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
struct Node{
    int v,r,s;
    Node* ch[2];
    int cmp(int x)const{
        if(x==v)return -1;
        return x>v?1:0;
    }
    void push_up(){
        s=ch[0]->s+ch[1]->s+1;
    }
};
Node* null=new Node();
Node* root=null;
int i,j,k,n,m,x,y,tot,d,sum;
char c[1];
void rotate(Node* &o,int d){
    Node* k=o->ch[d^1];
    o->ch[d^1]=k->ch[d];
    k->ch[d]=o;
    o->push_up();
    k->push_up();
    o=k;
}
void insert(Node* &o,int x){
    if(o==null){
        o=new Node();
        o->ch[0]=o->ch[1]=null;
        o->v=x;
        o->r=rand();
        o->s=1;
    }else{
        int d=o->v>x?0:1;
        insert(o->ch[d],x);
        if(o->ch[d]->r>o->r)rotate(o,d^1);
    }
    o->push_up();
}
int del(Node* &o,int x){
    if(o==null)return 0;
    if(o->v<x){
        int t=o->ch[0]->s+1;
        o=o->ch[1];
        return t+del(o,x);
    }else{
        int t=del(o->ch[0],x);
        o->s-=t;
        return t;
    }
}
int find(Node* o,int x){
    int s=o->ch[1]==null?0:o->ch[1]->s;
    if(s+1==x)return o->v;
    if(s>=x)return find(o->ch[1],x);
    return find(o->ch[0],x-s-1);
}
int main()
{
    scanf("%d%d",&n,&m);
    d=tot=0;
    for(i=1;i<=n;i++){
        scanf("%s%d",c,&x);
        if(c[0]=='I')if(x>=m)insert(root,x-d);
        if(c[0]=='A')d+=x;else
        if(c[0]=='S'){
            d-=x;
            tot+=del(root,m-d);
        }else if(c[0]=='F')if(x>root->s)printf("-1\n");else printf("%d\n",find(root,x)+d);
    }
    printf("%d\n",tot);
    return 0;
}
bzoj1503

 

posted @ 2016-08-25 19:46  gjghfd  阅读(171)  评论(0编辑  收藏  举报