BZOJ1503 NOI2004 郁闷的出纳员 平衡树

题意:开始时给定一个空的数列,要求维护:1、加入一个数  2、数列中所有元素+k  3、数列中所有元素-k  4、查询数列中的第k大。其中对于任意时刻,如果有一个元素<Min,则删除该元素。

题解:平衡树裸题……话说当年还打算把Splay Treap SBT都学一下,结果现在只会Splay了QAQ

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <climits>
#include <iostream>
#include <algorithm>
using namespace std;
#define Pushup(x) tree[x].cnt=tree[tree[x].child[0]].cnt+tree[tree[x].child[1]].cnt+1

const int MAXN=200000+2;
struct NODE{
    int value,cnt,child[2];
}tree[MAXN];
int N,Min,cnt,root,add;
char Order[2];

void Rotate(int &x,bool type){
    int y=tree[x].child[!type];
    tree[x].child[!type]=tree[y].child[type],tree[y].child[type]=x;
    tree[y].cnt=tree[x].cnt,Pushup(x);
    x=y;
}

void Maintain(int &x,bool type){
    if(tree[tree[tree[x].child[type]].child[type]].cnt>tree[tree[x].child[!type]].cnt) Rotate(x,!type);
    else if(tree[tree[tree[x].child[type]].child[!type]].cnt>tree[tree[x].child[!type]].cnt) Rotate(tree[x].child[type],type),Rotate(x,!type);
    else return;

    Maintain(tree[x].child[0],false),Maintain(tree[x].child[1],true);
    Maintain(x,true),Maintain(x,false);
}

void Insert(int &x,int value){
    if(x){
        tree[x].cnt++;
        if(value<tree[x].value) Insert(tree[x].child[0],value);
        else Insert(tree[x].child[1],value);
        Maintain(x,value>=tree[x].value);

    }
    else{
        x=++cnt;
        tree[x].child[0]=tree[x].child[1]=0;
        tree[x].cnt=1,tree[x].value=value;
    }
}

void Delete(int &x,int v,int minv){
    if(!x) return;

    if(tree[x].value+v<minv) Delete(x=tree[x].child[1],v,minv);
    else{
        Delete(tree[x].child[0],v,minv);
        Pushup(x);
    }
}

int Select(int &x,int k){
    int c=tree[tree[x].child[1]].cnt+1;

    if(c==k) return tree[x].value;
    else if(c<k) return Select(tree[x].child[0],k-c);
    else return Select(tree[x].child[1],k);
}

int main(){
    cin >> N >> Min;
    for(int k,t;N--;){
        scanf("%s %d",Order,&k);

        if(Order[0]==‘I‘ && k>=Min) Insert(root,k-add);
        if(Order[0]==‘A‘) add+=k;
        if(Order[0]==‘S‘) add-=k,Delete(root,add,Min);
        if(Order[0]==‘F‘) cout << (k>tree[root].cnt?-1:Select(root,k)+add) << endl;
    }
    cout << cnt-tree[root].cnt << endl;

    return 0;
}

时间: 2024-08-08 05:35:49

BZOJ1503 NOI2004 郁闷的出纳员 平衡树的相关文章

bzoj 1503: [NOI2004]郁闷的出纳员 平衡树

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 12250  Solved: 4372[Submit][Status][Discuss] Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之

bzoj1503 [NOI2004]郁闷的出纳员(名次树+懒惰标记)

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 8705  Solved: 3027[Submit][Status][Discuss] Description OIER 公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是, 我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反

[BZOJ1503][NOI2004]郁闷的出纳员 无旋Treap

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调

BZOJ1503 [NOI2004]郁闷的出纳员

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1503 [我的感受] 这题郁闷了很久,因为discuss里讨论的问题和我都不是一个问题... discuss里的当然是一大坑点啦,就是初始工资挂了的不算在最后踢出的人数中. 不过这个我倒是刚开始就这么打的...不过我一直超时啊超时啊... 终于要来了数据...额,原来是平衡树的性质都没怎么用...根本没转几次啊,然后数据就特意卡了这个,连续添加递增工资的人[变成了链] 那我就随机转一转好了

[BZOJ1503] [NOI2004] 郁闷的出纳员 (treap)

Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司

【权值分块】bzoj1503 [NOI2004]郁闷的出纳员

权值分块,离散化非常蛋疼,只能离散化搞…… 需要支持操作:删除<=某个值得所有权值==打标记 O(sqrt(n)) 码长和我的平衡树差不多……速度快3倍左右. 1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 using namespace std; 6 #define N 201001 7 struct Point{int v,p;}tmp

bzoj1503: [NOI2004]郁闷的出纳员 fhqtreap版

这道题写法和之前差不多 但是fhqtreap在加点的时候为了同时维护大根堆以及二叉排序树的性质所以插入时也要注意分裂 fhqteap需要判断指针是否为空 不然就会re 这个我调了很久 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int M=150000; int read(){ int ans=0,f=1,c=getchar(); while(c<

[BZOJ 1503] [NOI2004] 郁闷的出纳员

1503: [NOI2004] 郁闷的出纳员 Time Limit: 5 SecMemory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调整

bzoj 1503: [NOI2004]郁闷的出纳员 -- 权值线段树

1503: [NOI2004]郁闷的出纳员 Time Limit: 5 Sec  Memory Limit: 64 MB Description OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除一个相同的量.我真不知道除了调工资他还做什么其它事情.工资的频繁调