{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();
}
浙公网安备 33010602011771号