NKOI 1344 人力资源管理

人力资源管理

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 7
1 10
3 6
2 9
3 6  
样例输入2:
4 4                             
4 1 2 5                       
1 3
3 3
2 4
3 1

Sample Output

样例输出1:
3
2
样例输出2:
2
3

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值