{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();

}

 

你可能感兴趣的:(struct)