线段数例题4
人力资源
某公司有n个员工,每个员工有一个工作能力值(50000以内的自然数)。tom是公司人力资源部门的主管,他可以进行如下3种操作:
1.Tom为公司招聘了一个能力值为x的新员工
2.Tom为公司辞退了一个能力值为y的员工
3.Tom要找出在所有员工能力值由高到低的排名中,能力值大于W的员工的人数
输入:
第一行两个整数n,m 表示有n个员工,和tom的m项工作
接下来一行,n个整数,表示n个员工的能力值
接下来m行,每行有两个整数a,b。
a=1 表示招聘了一个能力值为b的新员工
a=2 表示辞退了一个能力值为b的员工
a=3 表示查出能力值>b的员工的个数,并输出排名结果
输出:
若干行,每行一个整数,表示输入中所有a=3的操作的结果。
样例输入:
6 5
9 4 6 2 3 5
1 7
1 10
3 6
2 9
3 6
样例输出:
3
2
#include <cstdio> #include <cstdlib> #include <iostream> #include <cstring> #include <string> #include <cmath> #include <algorithm> using namespace std; struct node { int a,b,l,r,cnt; }; node tree[130000]; int tot=0; int n,m,x,y,i,t,ans; void build(int x,int y) { int now=++tot; tree[now].a=x; tree[now].b=y; tree[now].cnt=0; if(x<y) { tree[now].l=tot+1; build(x,(x+y)/2); tree[now].r=tot+1; build((x+y)/2+1,y); } } void insert(int p,int k) { if(tree[p].a<=k&&k<=tree[p].b) { tree[p].cnt++; insert(tree[p].l,k); insert(tree[p].r,k); } } void Delete(int p,int k) { if(tree[p].a<=k&&k<=tree[p].b) { if(tree[p].a==tree[p].b&&tree[p].cnt) { tree[p].cnt--; return; } Delete(tree[p].l,k); Delete(tree[p].r,k); tree[p].cnt=tree[tree[p].l].cnt+tree[tree[p].r].cnt; } } int getans(int p,int x,int y) { if(x<=tree[p].a&&tree[p].b<=y)return tree[p].cnt; int lcnt=0,rcnt=0,mid=(tree[p].a+tree[p].b)/2; if(x<=mid)lcnt=getans(tree[p].l,x,y); if(y>mid)rcnt=getans(tree[p].r,x,y); return(lcnt+rcnt); } int main() { build(1,60001); scanf("%d%d",&n,&m); for(i=1;i<=n;i++) { scanf("%d",&t); insert(1,t); } for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); if(x==1)insert(1,y); if(x==2)Delete(1,y); if(x==3) { ans=getans(1,y+1,60001); printf("%d\n",ans); } } return 0; }