HDU 4217 Data Structure?(线段树 or 树状数组啊)

来源:互联网 发布:淘宝上能买到真阿胶吗 编辑:程序博客网 时间:2024/05/16 18:56

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4217


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 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
23 21 110 33 9 1
 

Sample Output
Case 1: 3Case 2: 14
 

Author
iSea@WHU
 

Source
首届华中区程序设计邀请赛暨第十届武汉大学程序设计大赛


题意:

n个数为 1 → n,一共有 k 次操作,每次取出第 ki 小的数。

问所有取出数字之和。

(树状数组)

代码如下:

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>using namespace std;#define maxn 262147#define LL __int64int c[maxn], a[maxn];int n, k;int Lowbit(int x)  // 2^k{    return x&(-x);}void update(int i, int x)//i点增量为x{    while(i <= n)    {        c[i] += x;        i += Lowbit(i);    }}int sum(int x)//区间求和 [1,x]{    int sum=0;    while(x>0)    {        sum+=c[x];        x-=Lowbit(x);    }    return sum;}int er_find(int kk){    int L = kk, R = n;    int tmp = kk;    while(L <= R)    {        int mid = L+(R-L)/2;        int tt = sum(mid);        if(tt == kk)        {            tmp = mid;            R = mid-1;        }        else if(tt < kk)        {            L = mid+1;        }        else if(tt > kk)        {            R = mid-1;        }    }    return tmp;}int main(){    int t;    int cas = 0;    scanf("%d",&t);    while(t--)    {        memset(c,0,sizeof(c));        scanf("%d%d",&n,&k);        for(int i = 1; i <= n; i++)        {            update(i,1);        }        int ki;        LL ans = 0;        for(int i = 1; i <= k; i++)        {            scanf("%d",&ki);            int tmp = er_find(ki);            ans += tmp;            update(tmp, -1);//减一变为0        }        printf("Case %d: %I64d\n",++cas,ans);    }    return 0;}/*993 21 110 33 9 110 51 2 3 4 510 41 2 3 410 55 4 3 2 110 51 5 7 4 2*/

贴一发别人的线段树:http://www.cnblogs.com/xiaohongmao/archive/2012/04/29/2476452.html

#include <stdio.h>#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1const int maxn = 300000;int tree[maxn<<2];int temp;void build(int l,int r,int rt){    tree[rt]=r-l+1;    if(l==r)        return;    int m=(l+r)>>1;    build(lson);    build(rson);}void dele(int del,int l,int r,int rt){    tree[rt]--;//0 已取    if(l==r)    {        temp=l;        return;    }    int m=(l+r)>>1;    if(del<=tree[rt<<1])        dele(del,lson);    else    {        del-=tree[rt<<1];        dele(del,rson);    }}int main(){    int t,n,k,ki,i;    int nCase=1;    __int64 sum;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&k);        build(1,n,1);        sum=0;        for(i=0; i<k; i++)        {            scanf("%d",&ki);            dele(ki,1,n,1);            sum+=temp;        }        printf("Case %d: %I64d\n",nCase++,sum);    }    return 0;}


1 0