首页 > 编程语言 > 详细

[ZJOI2006]书架(二分+树状数组)

时间:2019-05-23 14:00:35      阅读:97      评论:0      收藏:0      [点我收藏+]

这题90%以上的人做法为裸的平衡树,实际上根本没必要还常数大,最好的方法是二分+树状数组。具体做法是,开3倍内存,初始把中间n位赋值为1。对于每个操作:1&2、删除该位,将其丢在头/尾(开三倍内存的原因)。3、插入时直接二分查询第ask(x)+y位,换一下即可。4、直接查询。5、二分查询。复杂度O(nlog2n)

技术分享图片
#include<bits/stdc++.h>
using namespace std;
const int N=240010;
int n,m,a[N],id[N],c[N];
void add(int x,int v){while(x<=2*m+n)c[x]+=v,x+=x&-x;}
int ask(int x){int ret=0;while(x)ret+=c[x],x-=x&-x;return ret;}
int find(int x)
{
    int l=1,r=2*m+n,mid,pos=2*m+n;
    while(l<=r)
    {
        mid=l+r>>1;
        if(ask(mid)>=x)pos=mid,r=mid-1;
        else l=mid+1;
    }
    return pos;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1,x;i<=n;i++)scanf("%d",&a[i+m]),id[a[i+m]]=i+m,add(i+m,1);
    for(int i=1;i<=m;i++)
    {
        char str[10];int x,y,t,pos,tmp;
        scanf("%s%d",str,&x);
        if(str[0]==T)pos=find(1),add(id[x],-1),add(pos-1,1),id[x]=pos-1,a[id[x]]=x;
        if(str[0]==B)pos=find(n),add(id[x],-1),add(pos+1,1),id[x]=pos+1,a[id[x]]=x;
        if(str[0]==I)
        {
            scanf("%d",&y);
            if(!y)continue;
            pos=find(ask(id[x])+y),tmp=a[pos];
            swap(a[pos],a[id[x]]),swap(id[x],id[tmp]);
        }
        if(str[0]==A)printf("%d\n",ask(id[x])-1);
        if(str[0]==Q)printf("%d\n",a[find(x)]);
    }
}
View Code

 

[ZJOI2006]书架(二分+树状数组)

原文:https://www.cnblogs.com/hfctf0210/p/10911340.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!