HDU 4217 Data Structure?(树状数组/二分)

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.
在一个含有1-n的序列中,每次找到第Ki小的数,并把它删除。
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 <= T <= 128
1 <= K <= N <= 262 144
1 <= Ki <= N - i + 1
第一个数T,表示测试数据的组数。
每组测试数据,第一行2个整数n和m,m表示操作的轮数。
接下来m行,每行一个整数k,表示要找出第k小的数,并把它删除。
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

树状数组记录数字是第几个,中间用二分查找,
可惜我二分全忘光了

#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <queue>
#include <vector>
#include <map>
#include <string>

using namespace std;
//for(i=1;i<n;i++)
//scanf("%d",&n);
//printf("\n",);
//memset(num,0,sizeof(num));

long long tree[400000],ans;
int key[400000];
int main()
{
    long long i,j,k,n,t,l,m,temp,tt;

    scanf("%lld",&t);

    for(l=1;l<=t;l++)
    {
        scanf("%lld%lld",&n,&m);

        for(i=1;i<=n;i++)
        {
            k=i;

            while(k<=n)
            {
                tree[k]+=1;
                k+=((-k)&k);
            }
        }


        ans=0;

        for(i=1;i<=m;i++)
        {
            temp=0;
            scanf("%lld",&j);
            tt=j;

            int st=0,en=n,mid;

            while(st+1<en)
            {
                mid=(st+en)/2;

                temp=0;
                k=mid;
                while(k>0)
                {
                    temp+=tree[k];
                    k-=((-k)&k);
                }

                if(temp>=j)
                {
                    en=mid;
                }
                else
                {
                    st=mid;
                }

            }




            k=en;

            while(k<=n)
            {
                tree[k]-=1;
                k+=((-k)&k);
            }


            ans+=en;
        }
        printf("Case %lld: %lld\n",l,ans);

        memset(tree,0,sizeof(tree));
        memset(key,0,sizeof(key));
    }

//memset(num,0,sizeof(num));
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值