zoukankan      html  css  js  c++  java
  • [ZJOI2006]书架(二分+树状数组)

    这题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
    ",ask(id[x])-1);
            if(str[0]=='Q')printf("%d
    ",a[find(x)]);
        }
    }
    View Code
  • 相关阅读:
    C:大数相加
    杭电2186:悼念512汶川大地震遇难同胞——一定要记住我爱你
    实验五
    安装vmtools
    ubuntu20.04换源
    实验一 灯程序——OK6410A开发板LINUX3.0.1(嵌入式开发)
    OK6410A开发板LINUX3.0.1配置(嵌入式开发)
    实验四 Makefile
    虚拟机联网
    实验三 按键灯
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10911340.html
Copyright © 2011-2022 走看看