NKOI 1344 人力资源管理

来源:互联网 发布:高中英语语法视频 知乎 编辑:程序博客网 时间:2024/05/16 06:54

人力资源管理

Time Limit:10000MS  Memory Limit:65536K
Total Submit:230 Accepted:141
Case Time Limit:1000MS

Description

某公司有n个员工,每个员工有一个工作能力值(该值为60000以内的自然数)。
Tom是公司人力资源部门的主管,他可以进行如下3种操作:
1.Tom为公司招聘了一个能力值为x的新员工

2.Tom为公司辞退了一个能力值为y的员工

3.Tom要查出在所有员工能力值由高到低的排名中,能力值大于W的员工的人数

Input

第一行两个整数n,m 表示有n个员工,和tom的m项工作

接下来一行,n个整数,表示n个员工的能力值

接下来m行,每行有两个整数a,b(1<=b<=60000)。

a==1 表示招聘了一个能力值为b的新员工

a==2 表示辞退了一个能力值为b的员工(若没有能力值为b的员工,则该操作无效)

a==3 表示查出能力值>b的员工的个数,并输出结果

Output

若干行,每行一个整数,表示输入中所有a==3的操作的结果。

Sample Input

样例输入1:6 5                                      9 4 6 2 3 5                          1 71 103 62 93 6  样例输入2:4 4                             4 1 2 5                       1 33 32 43 1

Sample Output

样例输出1:32样例输出2:23

Hint

n,m<=100000


分析:
     题中给出,每个员工的能力值在60000以内,我们可以建立一个表示区间[1,60001]的线段树。
    线段树的节点struct node{ int a, b, L, R, Cnt; };  
    Cnt记录该出现在区间[a,b]中的数字个数
查询能力值大于y的人的个数即查询能力值在y+1到60001的人数即可

#include<iostream>#include<cstdio>using namespace std;const int maxn=60001;inline void _read(int &x){char t=getchar();bool sign=true;while(t<'0'||t>'9'){if(t=='-')sign=false;t=getchar();}for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0';if(!sign)x=-x;}int n,m,a,b,s[maxn+2],tot;struct wk{int left,right,a,b,v;}tree[2*maxn];void insert(int x,int y){int r=++tot;tree[r].a=x;tree[r].b=y;if(x<y){tree[r].left=tot+1;insert(x,(x+y)/2);tree[r].right=tot+1;insert((x+y)/2+1,y);tree[r].v=tree[tree[r].left].v+tree[tree[r].right].v;}else tree[r].v=s[x];}void change(int r){if(b==tree[r].a&&b==tree[r].b){    if(a==1)tree[r].v++;    else if(tree[r].v)tree[r].v--;    return;}if(tree[r].left&&tree[tree[r].left].a<=b&&tree[tree[r].left].b>=b)    change(tree[r].left);if(tree[r].right&&tree[tree[r].right].a<=b&&tree[tree[r].right].b>=b)    change(tree[r].right);tree[r].v=tree[tree[r].left].v+tree[tree[r].right].v;}int getnum(int r){if(tree[r].a>b&&tree[r].b<=maxn)return tree[r].v;int total=0;if(tree[r].left&&tree[tree[r].left].b>b)total+=getnum(tree[r].left);if(tree[r].right&&tree[tree[r].right].b>b)total+=getnum(tree[r].right);return total;}int main(){_read(n);_read(m);for(int i=1;i<=n;i++){_read(a);s[a]++;}insert(0,maxn);for(int i=1;i<=m;i++){_read(a);_read(b);if(a==1||a==2)change(1);else printf("%d\n",getnum(1));}}

0 0