Codeforces edu 87(D. Multiset)树状数组+二分

给你一串数组a(有序),再给你q次操作,每次操作给你一个数k,如果k大于0,则将k按顺序插入到数组a中,若k小于0,则将数组中第 | k | 大的数删除,最后输出数组a中的任意一个数,若数组a中没有数则输出0
注意:该题内存限制为28M
最先想到用multiset去做,但是由于multiset是集合,没法像数组那样通过下标访问某个元素,遍历的话又会超时。。。。然后就恰饭去了。。。。

经大佬点播,用树状数组去维护每个数的个数,比如1,1,2,3,5中,1的个数就是2,即a[1]=2,用树状数组维护这个数组a。然后进行删除操作时用二分查找第k个数是哪个,再删除它。

代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;

int N[1050000];
int n,q,k;
int lowbit(int x)
{return x&(-x);}
void insertt(int x,int a)
{
    while(x<=n)
    {N[x]+=a;
    x+=lowbit(x);}
}
int query(int x,int y)
{
    x--;
    int ans1=0,ans2=0;
    while(x>0)
    {ans1+=N[x];
    x-=lowbit(x);}
    while(y>0)
    {ans2+=N[y];
    y-=lowbit(y);}
    return ans2-ans1;
}
int ef(int x)
{
    int l=1,r=n,ansl;
    while(l<r)
    {
        int mid=(l+r)/2;
        ansl=query(l,mid);
        if(ansl<x)
        {l=mid+1;
        x-=ansl;}
        else
        {r=mid;}
    }
    return l;
}
int main()
{
    int a,pos;
    scanf("%d %d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a);
        insertt(a,1);
    }
    while(q--)
    {
        scanf("%d",&k);
        if(k>0)
        {insertt(k,1);}
        else
        {pos=ef(-k);
        insertt(pos,-1);}
    }
    if(query(1,n)==0)
    {printf("0\n");}
    else
    {
        pos=ef(1);
        printf("%d\n",pos);
    }
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值