2 3 2 1 1 10 3 3 9 1
Case 1: 3 Case 2: 14
题意:n个数1-n,k次操作,每次取出第ki小的数。问所有取出数字之和。
思路:树状数组。开始所有位置都是1,如果有数字被去掉就-1。然后在查找第ki小的数字的时候,利用树状数组去进行求和,看数字个数为k时是第几个。
代码:
#include <stdio.h> #include <string.h> #include <iostream> using namespace std; const int N = 277777; int t, n, m, bit[N], num, i; long long ans; void add(int x, int v) { while (x <= n) { bit[x] += v; x += (x&(-x)); } } int Sum(int k) { int num = 0; int x = 0; for (int i = 18; i >= 0; i--) { if (x + (1<<i) <= n && bit[x + (1<<i)] + num < k) { x += (1<<i); num += bit[x]; } } return x + 1; } void init() { ans = 0; memset(bit, 0, sizeof(bit)); scanf("%d%d", &n, &m); for (i = 1; i <= n; i++) add(i, 1); for (i = 0; i < m; i++) { scanf("%d", &num); int s = Sum(num); ans += s; add(s, -1); } } int main() { int cas = 0; scanf("%d", &t); while (t--) { init(); //printf("Case %d: %lld\n", ++cas, ans); cout <<"Case "<<++cas<<": "<<ans<<endl; } return 0; }