Data structure is one of the basic skills for Computer Science students, which is a particular way of storing and organizing data in a computer so that it can be used efficiently. Today let me introduce a data-structure-like problem for you.
Original, there are N numbers, namely 1, 2, 3...N. Each round, iSea find out the Ki-th smallest number and take it away, your task is reporting him the total sum of the numbers he has taken away.
Input
The first line contains a single integer T, indicating the number of test cases.
Each test case includes two integers N, K, K indicates the round numbers. Then a line with K numbers following, indicating in i (1-based) round, iSea take away the Ki-th smallest away.
Technical Specification
1. 1 <= T <= 128
2. 1 <= K <= N <= 262 144
3. 1 <= Ki <= N - i + 1
Output
For each test case, output the case number first, then the sum.
Sample Input
2
3 2
1 1
10 3
3 9 1
Sample Output
Case 1: 3
Case 2: 14
题意:
给你一段数组让你每次询问找出这段中第K小的数获取到之和并把他在原来的地方删除求获取到的数字之和
思路:
先建一个线段树把每一段赋值为1然后每查询一个数让所在查询区间的所有减一然后让左区间加上总和(总和一开始为0),
如果左区间的之和小于等于价值找左区间把价值减去左区间值,否则右区间查询
代码如下:
#include<iostream>
using namespace std;
long long a[10000009];long long sum,n,k;
void pushup(long long step)
{
a[step] = a[step<<1] + a[step<<1|1];
}
void build(long long l,long long r,long long step)
{
if(l == r)
{
a[step] = 1;
return ;
}
long long m = (l+r)>>1;
build(l,m,step<<1);
build(m+1,r,step<<1|1);
pushup(step);//建树
}
void updata(long long v,long long l,long long r,long long step)
{
a[step]--;//每找的区间减一
if(l == r)
{
sum+=l;//让sum存找到之和
return ;
}
long long m = (l+r)>>1;
if(v <= a[step<<1] )//更新左区间
{
updata(v,l,m,step<<1);
}
else{
updata(v-a[step<<1],m+1,r,step<<1|1);//更新右区间
}
}
int main()
{
long long t;
scanf("%lld",&t);long long yy = 1;
while(t--)
{
scanf("%lld%lld",&n,&k);
long long h;sum = 0;
build(1,n,1);
for(long long i=0;i<k;++i)
{
scanf("%lld",&h);
updata(h,1,n,1);
}
printf("Case %lld: %lld\n",yy,sum);yy++;//输出
}
return 0;
}