很简单很直接的线段树。
/* * Author: stormdpzh * HDOJ: 4217 Data Structure? * Time: 2012/4/25 12:09:16 */ #include <iostream> #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <vector> #include <queue> #include <stack> #include <set> #include <algorithm> #include <functional> #define sz(v) ((int)(v).size()) #define rep(i, n) for(int i = 0; i < n; i++) #define repf(i, a, b) for(int i = a; i <= b; i++) #define out(n) printf("%d", n) #define wh(n) while(scanf("%d", &n) != EOF) #define whz(n) while(scanf("%d", &n) != EOF && n != 0) #define int64 long long using namespace std; const int Max = 262150; int n, k; int num[4 * Max]; void build(int l, int r, int i) { num[i] = r - l + 1; if(r == l) return; int mid = (l + r) >> 1; build(l, mid, i << 1); build(mid + 1, r, i * 2 + 1); } int search(int l, int r, int tmp, int i) { num[i]--; if(l == r) return l; int mid = (l + r) >> 1; int tmp_res; if(num[i << 1] >= tmp) return search(l, mid, tmp, i << 1); else return search(mid + 1, r, tmp - num[i << 1], i * 2 + 1); } int main() { int t; scanf("%d", &t); int ans = 1; while(t--) { scanf("%d%d", &n, &k); build(1, n, 1); int64 res = 0; rep(i, k) { int tmp; scanf("%d", &tmp); res += (int64)search(1, n, tmp, 1); } printf("Case %d: %I64d\n", ans++, res); } return 0; }