这题就是给了你三种操作,
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; }
HDU2852 KiKi's K-Number 树状数组+二分,码迷,mamicode.com
HDU2852 KiKi's K-Number 树状数组+二分
时间: 2024-10-11 08:24:40