题解
基础线段树动态查询第k小操作
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
const int INF = 0x3f3f3f3f;
int n, m, k;
namespace segment_tree {//线段树板子
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
int sum[N*4];
void pushup(int rt) {
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l, int r, int rt) {
//记得初始化
if (l == r) {
sum[rt]=1;
return;
}
int mid = l + r >> 1;
build(lson);
build(rson);
pushup(rt);
}
int query(int k, int l, int r, int rt) {
if (l==r) {
sum[rt]=0;
return l;
}
int mid = l + r >> 1;
int tmp=sum[rt<<1];//查询左字数的总数
int ans=0;
if (k <= tmp) ans=query(k,lson);
else ans=query(k-tmp,rson);
pushup(rt);
return ans;
}
}
using namespace segment_tree;
int main() {
ios::sync_with_stdio(0);
int T;
cin>>T;
for (int cs = 1; cs <= T; ++cs) {
printf("Case %d: ",cs);
cin>>n>>k;
build(1,n,1);
ll res=0;
for (int i = 1,x; i <= k; ++i) {
cin>>x;
res+=query(x,1,n,1);
}
printf("%lld\n", res);
}
return 0;
}