链接:
https://www.nowcoder.com/acm/contest/93/L
来源:牛客网
来源:牛客网
题目描述
你们wyh学长小时候住在河边,因为周围的生态环境非常好,所以经常会有天鹅浮在湖面上,每只天鹅都长得不一样,它们偶尔排成一排,偶尔分散开,偶尔也会去其他河畔,wyh学长为了统计它们的个数,编了一个程序赋予它们一个“萌”值,但是这些天鹅很不听话,一会儿会从别的地方游过来一两只,一会儿又会在统计过程中游走一两只,现在请你帮他完成统计任务。
输入描述:
共有T(T<=10)组数据,每组数据第一行为两个数 N, M (N,M <= 500000),代表有N只天鹅和M次操作,接下来一行是N个数字,下面M行首先会输入一个字符串S,接着会有三类操作,如果S是“insert”,接着输入一个正整数a,代表插入一只“萌”值为a的天鹅,如果S是“delete”,接着输入一个正整数a,代表删除一只“萌”值为a的天鹅,如果S是“query”,接着输入一个正整数k,代表查询“萌”值第k大的天鹅。 萌值为[1,1000000000],并且保证一定存在第k大
输出描述:
对应每次询问,输出询问结果。
题解:
坐标1~1000000000,无法直接开数组,可以通过动态线段树来求解
注意:开始的时候每次循环都用memset对数组初始化,这样虽然可以过但是
耗时很大,后来发现其实可以每开辟一个新节点的时候对他初始化。
代码:
#include<bits/stdc++.h>
using namespace std;
int cnt;
struct node
{
int l,r;
int lson,rson;
int num;
}tree[20000002];
void add(int rt,int L,int k)
{
if(tree[rt].l==tree[rt].r)
{
tree[rt].num+=k;
return;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(L<=mid)
{
if(tree[rt].lson==0)
{
tree[rt].lson=cnt++;int id=cnt-1;
tree[id].l=tree[rt].l;
tree[id].r=mid;
tree[id].lson=tree[id].rson=0;
tree[id].num=0;
}
add(tree[rt].lson,L,k);
}
else
{
if(tree[rt].rson==0)//开辟新节点
{
tree[rt].rson=cnt++;int id=cnt-1;
tree[id].l=mid+1,tree[id].r=tree[rt].r;
tree[id].lson=tree[id].rson=0;//新节点左右节点不存在
tree[id].num=0;
}
add(tree[rt].rson,L,k);
}
int l=tree[rt].lson,r=tree[rt].rson;
tree[rt].num=tree[l].num+tree[r].num;
}
int query(int rt,int k)
{
if(tree[rt].l==tree[rt].r)
return tree[rt].l;
int l=tree[rt].lson,r=tree[rt].rson;
if(tree[r].num>=k)return query(r,k);
else return query(l,k-tree[r].num);
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
//memset(tree,0,sizeof(tree));
tree[1].l=1;tree[1].r=1000000000;
tree[1].lson=tree[1].rson=0;
tree[1].num=0;
cnt=2;
int n,m;scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
int x;scanf("%d",&x);
add(1,x,1);
}
while(m--)
{
char t[22];int k;scanf("%s%d",&t,&k);
if(t[0]=='i')add(1,k,1);
else if(t[0]=='d')add(1,k,-1);
else printf("%d\n",query(1,k));
}
}
return 0;
}