[hdu4217]Data Structure?

Time Limit: 10000/5000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)

Problem Description
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 N numbers, namely 1 , 2 , 3... N 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 T , indicating the number of test cases.
Each test case includes two integers N N , K , K K, K indicates the round numbers. Then a line with K K numbers following, indicating in i i (1-based) round, iSea take away the K i Ki -th smallest away.

Technical Specification

1 <= T <= 128
1 <= K <= N <= 262 144
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

题意:
给定 n n 个数字 1 1 n n ,将他们存在集合中,有 K K 组询问,每次询问一个数字 k i ki ,将集合中的第 k i ki 小的数字加到ans上,并将其从集合中删去,问 K K 次操作之后,ans为多少。

题解:
权值线段树,每次查询前缀和为 k i + 1 ki+1 的位置,并将其设为0即可。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct seg{
    int l,r,w;
}tr[1000004];
int n;
ll ans;
void build(int k,int l,int r){
    tr[k].l=l;tr[k].r=r;
    if(l==r){
        tr[k].w=1;
        return ;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
}
int work(int k,int x){
    int l=tr[k].l,r=tr[k].r;
    if(l==r){
        ans+=l;
        tr[k].w=0;
        return l;
    }
    int mid=(l+r)>>1;
    if(tr[k<<1].w>=x)work(k<<1,x);
    else work(k<<1|1,x-tr[k<<1].w);
    tr[k].w=tr[k<<1].w+tr[k<<1|1].w;
}
int w33ha(int CASE){
    scanf("%d",&n);
    build(1,1,n);
    ans=0;
    int K;scanf("%d",&K);
    for(int i=1;i<=K;i++){
        int x;scanf("%d",&x);
        work(1,x);
    }
    printf("Case %d: %lld\n",CASE,ans);
    return 0;
}

int main(){
    int T;scanf("%d",&T);
    for(int i=1;i<=T;i++)w33ha(i);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/dxyinme/article/details/94859453
今日推荐