线段树 树状数组 求大于某个值的第k小的数 hdu 2852 KiKi's K-Number

题意坑爹,应该是求大于a的第k小的数。。

线段树思路:更新操作就不说了,和另外一篇的一样

http://www.cnblogs.com/wuyiqi/archive/2011/12/26/2301504.html

关键是询问操作:问大于a的第k小的数,首先判断有几个数小于a,设为t,则题意就转换为了求整个区间的第k+t小的数

求之前先特判一下有没有k+t个数

线段树代码如下:

View Code
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 100010;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid (l+r)>>1
int sum[maxn<<2];
void update(int l,int r,int rt,int val,bool flag)
{
if(!flag) sum[rt]--;
else sum[rt]++;
// printf("sum[%d]=%d\n",rt,sum[rt]);
if(l==r) return;
int m=mid;
if(val<=m) update(lson,val,flag);
else update(rson,val,flag);
}
bool vis;
bool find(int l,int r,int rt,int a)
{
if(l==r&&l==a)
{
if(sum[rt]>=1) return true;
else return false;
}
int m=mid;
bool flag;
if(a<=m) flag=find(lson,a);
else flag=find(rson,a);
return flag;
}
void query(int l,int r,int rt,int k)
{
if(l==r)
{
printf("%d\n",l);
return ;
}
int m=mid;
if(k<=sum[rt<<1]) query(lson,k);
else query(rson,k-sum[rt<<1]);
}
int decide(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
// printf("sum[%d]=%d\n",rt,sum[rt]);
return sum[rt];
}
int m=mid;
int ret=0;
if(L<=m) ret+=decide(L,R,lson);
if(R>m) ret+=decide(L,R,rson);
return ret;
}
int main()
{
int m;
int op,a,k;
int n=100000;
while(scanf("%d",&m)!=EOF)
{
memset(sum,0,sizeof(sum));
while(m--)
{
scanf("%d",&op);
bool vis=false;
if(op==0)
{
scanf("%d",&a);
update(1,n,1,a,true);
}
if(op==1)
{
scanf("%d",&a);
if(!find(1,n,1,a)) printf("No Elment!\n");
else update(1,n,1,a,false);
}
if(op==2)
{
scanf("%d%d",&a,&k);
int t=decide(1,a,1,n,1);
// printf("t=%d\n",t);
int ans;
if(sum[1]<k+t) printf("Not Find!\n");
else query(1,n,1,k+t);
}
}
}
return 0;
}


用树状数组做了下,用上次的那种方法速度很快啊,开挂后果断rank1,因为这种方法是不用求和操作的

http://www.cnblogs.com/wuyiqi/archive/2011/12/25/2301071.html

附树状数组代码,rank1 截图一下,哈哈

 


 

 

 

 

View Code
#include<cstdio>
#include<cstring>
const int maxn = 100010;
int c[maxn];
int lowbit(int x){
return x&-x;
}
void update(int x,int d){
for(;x<=maxn;x+=lowbit(x))
c[x]+=d;
}
int sum(int x){
int ans=0;
for(;x>0;x-=lowbit(x))
ans+=c[x];
return ans;
}
int find_kth(int k){
int ans = 0, cnt = 0, i;
for (i = 20; i >= 0; i--){
ans += (1 << i);
if (ans >= maxn|| cnt + c[ans] >= k)
ans -= (1 << i);
else cnt += c[ans];
}
return ans + 1;
}
int find(int a, int k) {
int l = a + 1;
int r = maxn - 1;
int S = sum(a);
int ans = maxn;
while(l <= r) {
int m = (l + r) >> 1;
int nS = sum(m);
if(nS - S >= k) {
r = m - 1;
if(m < ans)
ans = m;
}else
l = m + 1;
}
return ans;
}
int main(){
int m,a,k,op;
while(scanf("%d",&m)!=EOF){
memset(c,0,sizeof(c));
while(m--){
scanf("%d",&op);
if(op==0){
scanf("%d",&a);
update(a,1);
}
if(op==1){
scanf("%d",&a);
if(sum(a)-sum(a-1)==0) printf("No Elment!\n");
else update(a,-1);
}
if(op==2){
scanf("%d%d",&a,&k);
/* int ans=find(a,k); //二分
if(ans==maxn)printf("Not Find!\n");
else printf("%d\n",ans);
*/
int ans=find_kth(k+sum(a));
if(ans>=maxn) printf("Not Find!\n");
else printf("%d\n",ans);
}
}
}
return 0;
}



posted @ 2011-12-29 14:25  Because Of You  Views(913)  Comments(0Edit  收藏  举报