首页 > 代码库 > HDU2852 KiKi's K-Number 树状数组+二分

HDU2852 KiKi's K-Number 树状数组+二分

这题就是给了你三种操作,

1:往容器中一个元素 x

2::把容器中的元素x删除

3:查询比 x大的第k个数


想法:添加元素跟删除元素  直接是以数本身为序号然后以 value值为1和-1即可,相当于计数,至于找比x第k个大的数,那就看看当前往后数k个数的第一个数是哪个就可以了,一开始直接找出来,然后往后暴力的扫了一遍,结果错了,没关系,反应很快,直接改了个二分查找,然后就过了,弄清楚如何建立这个树状数组即可


#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#include<cctype>

#define ll long long
#define LL __int64
#define eps 1e-8

//const ll INF=9999999999999;

#define inf 0xfffffff

using namespace std;


//vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p;

const int N = 100000 + 10;

int n;

int c[N];

void clear() {
	memset(c,0,sizeof(c));
}

int lowbit(int x) {
	return x&(-x);
}

//设原始矩阵为a,将a[i]加上val时对c所做的修改
void add(int i, int val) {
	while (i <= N) {
		c[i] += val;
		i += lowbit(i);
	}
} 

//求前i项元素的和
int get_sum(int i) {
	int sum = 0;
	while (i > 0) {
		sum += c[i];
		i -= lowbit(i);
	}
	return sum;
}

void cal(int a,int k) {
	int sum = get_sum(a);
	bool flag = false;
	int l = a + 1;
	int r = N;
	while(l < r) {
		int mid = (l + r)/2;
		int tmp = get_sum(mid);
		if(tmp < sum + k)
			l = mid + 1;
		else
			r = mid;
	}
	if(get_sum(l) >= k + sum) {
		printf("%d\n",l);
	}
	else
		puts("Not Find!");
}

int main() {
	int n;
	while(scanf("%d",&n) == 1) {
		clear();
		int x;
		for(int i=0;i<n;i++) {
			scanf("%d",&x);
			if(x == 0) {
				int y;
				scanf("%d",&y);
				add(y,1);
			}
			if(x == 1) {
				int y;
				scanf("%d",&y);
				if(get_sum(y) == get_sum(y - 1))
					puts("No Elment!");
				else
					add(y,-1);
			}
			if(x == 2) {
				int a,k;
				scanf("%d %d",&a,&k);
				cal(a,k);
			}
		}
	}
	return 0;
}