码迷,mamicode.com
首页 > 编程语言 > 详细

树状数组求第K小值 (spoj227 Ordering the Soldiers && hdu2852 KiKi's K-Number)

时间:2015-07-21 13:03:25      阅读:158      评论:0      收藏:0      [点我收藏+]

标签:树状数组   二分   

题目:http://www.spoj.com/problems/ORDERS/ and http://acm.hdu.edu.cn/showproblem.php?pid=2852

题意:spoj227:告诉每个位置前面有多少个数比当前位置小,求出原序列。hdu2852:设计一个容器,支持几种操作:增加/删除元素,求容器中比a大的数中第k小的数是多少。

分析:两个题思路都是求数组里面的第K小的数。开始一直在找O(N*logN)的方法,后来发现O(N*logN*logN)也是可以过的。。。两步:和先前的逆序数一样先用树状数组处理好比x小的数有多少个,然后二分~(值是单调的)

spoj227代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 2e5+6;
int lowbit[maxn],a[maxn],tree[maxn];
void GetLowbit()
{
	for(int i=1;i<maxn;i++)
		lowbit[i]=i&-i;
}
void update(int x,int v)
{
	for(int i=x;i<maxn && i;i+=lowbit[i])
		tree[i]+=v;
}
int query(int x)
{
	int ret(0);
	for(int i=x;i>0;i-=lowbit[i])
		ret+=tree[i];
	return ret;
}
int Find(int x,int n)
{
	int ret=1e9,down=1,mid,up=n,v;
	while(down<=up)
	{
		mid=(down+up)>>1;
		v=query(mid);
		if(v>=x)
		{
			up=mid-1;
			if(mid<ret && x==v)
				ret=mid;
		}
		else
			down=mid+1;
	}
	return ret;
}
int main()
{
	GetLowbit();
	int ncase,n,x,y,v,i,j;
	scanf("%d",&ncase);
	while(ncase--)
	{
		scanf("%d",&n);
		memset(tree,0,sizeof(tree[0])*(n+3));
		for(i=1;i<=n;i++)
		{
			update(i,1);
			scanf("%d",&a[i]);
		}
		for(i=n;i>=1;i--)
		{
			a[i]=Find(i-a[i],n);
			update(a[i],-1);
		}
		for(i=1;i<n;i++)
			printf("%d ",a[i]);
		printf("%d\n",a[n]);
	}
	return 0;
}

hdu2852代码:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn = 1e5+6;
int tree[maxn],cnt[maxn],lowbit[maxn];
void GetLowbit()
{
	for(int i=1;i<maxn;i++)
		lowbit[i]=i&-i;
}
void update(int x,int v)
{
	for(int i=x;i<maxn && i;i+=lowbit[i])
		tree[i]+=v;
}
int query(int x)
{
	int ret(0);
	for(int i=x;i>0;i-=lowbit[i])
		ret+=tree[i];
	return ret;
}
int Find(int a,int k)
{
	int down=a+1,mid,up=maxn-1,c=query(a),v,ret=1e9;
	while(down<=up)
	{
		mid=(down+up)>>1;
		v=query(mid)-c;
		if(v>=k)
		{
			up=mid-1;
			if(ret>mid)
				ret=mid;
		}
		else
			down=mid+1;
	}
	return ret;
}
int main()
{
	GetLowbit();
	int q,a,k,tp,v;
	while(scanf("%d",&q)!=EOF)
	{
		memset(tree,0,sizeof(tree));
		memset(cnt,0,sizeof(cnt));
		while(q--)
		{
			scanf("%d",&tp);
			if(tp==0)
			{
				scanf("%d",&v);
				cnt[v]++;
				update(v,1);
			}
			else if(tp==1)
			{
				scanf("%d",&v);
				if(cnt[v]>0)
				{
					cnt[v]--;
					update(v,-1);
				}
				else
					puts("No Elment!");
			}
			else
			{
				scanf("%d%d",&a,&k);
				int num=query(maxn-1)-query(a);
				if(num<k)
					puts("Not Find!");
				else
					printf("%d\n",Find(a,k));
			}
		}
	}
	return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

树状数组求第K小值 (spoj227 Ordering the Soldiers && hdu2852 KiKi's K-Number)

标签:树状数组   二分   

原文地址:http://blog.csdn.net/w20810/article/details/46981599

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!