題意就是在1~N中每次找到第k小的數並刪除,範圍固定第k小的數,就是樹狀數組或者線段樹的應用,一個細節是結果需要用long long,因爲262144*(262144+1)/2超過了32位表示範圍。
#include <cstdio>
#include <cstring>
#define MAX 262200
int n, q, c[MAX];
inline int lowbit(int x){
return x & -x;
}
void add(int x, int v)
{
for(; x <= n; x += lowbit(x)) c[x] += v;
}
int query(int x)
{
int s = 0;
for(; x; x -= lowbit(x)) s += c[x];
return s;
}
int find(int kth)
{
int l = 0, r = n;
while(l+1 < r){
int m = (l+r) >> 1;
if(query(m) >= kth) r = m;
else l = m;
}
return r;
}
int main()
{
int t = 1, test, k;
long long res;
for(scanf("%d", &test); t <= test; ++t){
scanf("%d%d", &n, &q);
memset(c+1, 0, n*sizeof(int));
for(int i = 1; i <= n; ++i) add(i, 1);
res = 0;
while(q--){
scanf("%d", &k);
k = find(k);
res += k;
add(k, -1);
}
printf("Case %d: %lld\n", t, res);
}
return 0;
}