Peng Lv

毋意,毋必,毋固,毋我。 言必行,行必果。

导航

{HDU}{4217}{Data Structure}{树状数组or线段树}

思路:在给定的序列中一次那周第Ki小的数,求和。这题用线段树很容易就AC我用的是树状数组,中间涉及到一个二分查找的过程,出了太多错误了,这个题WA成狗了。。。(1)二分中求最左的数(2)树状数组的初始化本题很特殊。。。

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <memory>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
#include <stack>
using namespace std;

const int MAXN = 280000;
const int INF = (1<<30);

#define CLR(x,y) memset(x,y,sizeof(x))
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
#define rep(i,x,y) for(i=x;i<y;++i)


long long tre[MAXN];
int n,t,tt,k;
int n_tre;
long long ans;

int lowbit(int x)
{
	return x&(-x);
}
void modify(int ind, const int& delta)
{
	for( ; ind <= n_tre; ind +=lowbit(ind))
		tre[ind] += delta;
}
int get_sum(int ind)
{
	int sum = 0;
	for( ; ind != 0; ind -= lowbit(ind))
		sum += tre[ind];
	return sum;
}
int b_search(const int& x)
{
	int mid,l,r;
	int tmp;
	l = 1;
	r = n_tre-1;
	while( l < r ){
		mid = (l+r)>>1;
		tmp = get_sum(mid);
		if( tmp >= x )
			r = mid;
		else
			l = mid + 1;
	}
	return l;
}
int init()
{
	int i;
	CLR(tre,0);
	rep(i,1,MAXN)
		tre[i] = lowbit(i);
	return 0;
}

int work()
{
	int i,j,tmp;
	long long ind,ans;
	n_tre = MAXN;
	rep(t,0,tt){
		init();
		ans = 0;
		scanf("%d%d",&n,&k);
		rep(i,0,k){
			scanf("%d",&tmp);
			ind = b_search(tmp);
			ans += ind;
			modify(ind,-1);
		}
		printf("Case %d: %I64d\n",t+1,ans);
	}
	return 0;
}
int main()
{
	scanf("%d",&tt);
	work();
}

 

posted on 2012-05-20 00:04  Lvpengms  阅读(301)  评论(0编辑  收藏  举报