• 动态排名系统(整体二分)


    题面

    第一道自己脑补出来的整体二分,这样我就不用去打那个树桩数组套主席树了

    开心

    主要是把各个操作分开

    op==1 则为加操作

    op==2 则为减操作

    op==3则为区间查询操作

    之后直接将询问的次数和值域二分求解即可

    #include<bits/stdc++.h>
    #define lowbit(x) x&(-x)
    using namespace std;
    const int N=1e5+7;
    const int INF=1e9+7;
    int m,n,T;
    int ans[N],num[N];
    struct node
    {
        int x,y,id,op;
        int k;
    } q[N],q1[N],q2[N];
    struct Tree
    {
        int tree[N<<2];
        void add(int x,int val)
        {
            for (;x<=n;x+=lowbit(x)) tree[x]+=val;
        }
        int query(int x)
        {
            int ans=0;
            for (;x;x-=lowbit(x)) ans+=tree[x];
            return ans;
        }
    } G;
    
    int cur[N];
    void solve(int from,int to,int l,int r)
    {
        if (from>to||l>r) return;
        if (l==r)
        {
            for (int i=from;i<=to;i++)
            if (q[i].op==3) ans[q[i].id]=l;
            return;
        }
        int mid=(l+r)>>1;
        for (int i=from;i<=to;i++)
        {
            if (q[i].k<=mid)
            {    
                if (q[i].op==2) G.add(q[i].x,-1);
                if (q[i].op==1) G.add(q[i].x,1);
            }
            if (q[i].op==3) cur[i]=G.query(q[i].y)-G.query(q[i].x-1);
        }
        for (int i=from;i<=to;i++)
        if (q[i].k<=mid)
        {
            if (q[i].op==2) G.add(q[i].x,1);
            if (q[i].op==1) G.add(q[i].x,-1);
        }
        int t1=0,t2=0;
        for (int i=from;i<=to;i++)
        if (q[i].op==1||q[i].op==2)
        {
            if (q[i].k<=mid) q1[t1++]=q[i];
            else q2[t2++]=q[i];
        }
        else 
        {
            if (cur[i]>=q[i].k) q1[t1++]=q[i];
            else q[i].k-=cur[i],q2[t2++]=q[i];
        }
        for (int i=0;i<t1;i++) q[from+i]=q1[i];
        for (int i=0;i<t2;i++) q[from+t1+i]=q2[i];
        solve(from,from+t1-1,l,mid);
        solve(from+t1,to,mid+1,r);
    }
    int main()
    {
        freopen("dynrank.in","r",stdin);
        freopen("dynrank.out","w",stdout);
        scanf("%d",&T);
        while (T--)
        {
            scanf("%d%d",&n,&m);
            for (int i=1;i<=n;i++)
            {
                int x;scanf("%d",&x);
                q[i].op=1;q[i].x=i;q[i].k=x;num[i]=x;
            }
            int tot=0;
            for (int i=1;i<=m;i++)
            {
                char s[5];int x,y,k;
                scanf("%s",s);scanf("%d%d",&x,&y);
                if (s[0]=='Q') {scanf("%d",&k);q[++n].op=3;q[n].x=x;q[n].y=y;q[n].id=++tot;q[n].k=k;}
                if (s[0]=='C')
                {
                    q[++n].op=2;q[n].x=x;q[n].k=num[x];
                    q[++n].op=1;q[n].x=x;q[n].k=y;num[x]=y;
                }
            }
            solve(1,n,0,INF);
            for (int i=1;i<=tot;i++) 
            printf("%d
    ",ans[i]);
        }
        return 0;
    }

     

    慢即是快,细则是能,于小处铸迤逦
  • 相关阅读:
    【Node】fs
    ☀【滚动条】动画,固定
    洛谷——P3817 小A的糖果
    洛谷——P1316 丢瓶盖
    洛谷—— P1190 接水问题
    CODEVS——T1332 上白泽慧音 || 洛谷——P1726 上白泽慧音
    CODEVS——T3008 加工生产调度
    python(20)- 列表生成式和生成器表达式练习Ⅱ
    MTK Android 编译命令
    第六届深圳国际物联网和智慧中国博览会(2014)总结
  • 原文地址:https://www.cnblogs.com/Hale522520/p/10861732.html
Copyright © 2020-2023  润新知