题目链接
权值线段树模板题(因为long long问题wa了一发),详细学习请参照其他大佬博客,代码仅供参考。
下面是ac代码:
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <set>
#include <algorithm>
#define ll long long
using namespace std;
const int N = 3e5+5;
struct Node
{
int l, r;
ll sum;
}tr[N<<2];
int n, m;
int mx;
void build(int p, int l, int r)
{
// mx = max(p, mx);
tr[p].l = l; tr[p].r = r;
if (l == r)
{
tr[p].sum = 1; return;
}
int mid = (l + r) >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
tr[p].sum = tr[p<<1].sum + tr[p<<1|1].sum;
}
int ask(int p, int x)
{
if (tr[p].l == tr[p].r) return tr[p].l;
int mid = (tr[p].l + tr[p].r) >>1;
if (tr[p<<1].sum >= x) return ask(p<<1, x);
else return ask(p<<1|1, x - tr[p<<1].sum);
}
void change(int p, int x)
{
if (tr[p].l == tr[p].r)
{
tr[p].sum = 0;
return;
}
int mid = (tr[p].l + tr[p].r) >> 1;
if (tr[p<<1].sum >= x) change(p<<1, x);
else change(p<<1|1, x - tr[p<<1].sum);
tr[p].sum = tr[p<<1].sum + tr[p<<1|1].sum;
}
void print()
{
for (int i = 1; i <= mx; i++)
cout << tr[i].l << " " << tr[i].r << " " << tr[i].sum <<endl;
cout <<"-----------" <<endl;
}
int main()
{
int t;
cin >> t;
int t0 = 1;
while(t--)
{
scanf("%d%d", &n, &m);
build(1, 1, n);
// print();
ll ans = 0;
for (int i = 1; i <= m; i++)
{
int x;
scanf("%d", &x);
ans += ask(1, x);
change(1, x);
}
printf("Case %d: ", t0++);
printf("%lld\n", ans);
}
return 0;
}