zoukankan      html  css  js  c++  java
  • 洛谷6186:[NOI Online 提高组]冒泡排序——题解

    https://www.luogu.com.cn/problem/P6186

    来蹭一波热度。

    猜一波这是一个结论题,然后就有https://www.cnblogs.com/qswg/p/9325210.html的结论了。

    结论:每进行一次冒泡排序,每个数的逆序对数就会左移一位并且-1(0除外)。

    也就是说,对于 $k$ 轮冒泡排序的询问,我们实际就是查找 $[k+1,n]$ 中的比 $k$ 大的数让其每个都减k的和。

    于是一度以为要写主席树了。

    但是对于第 $i$ 位数,它的逆序对数肯定 $le i-1$ ,所以我们只要放心大胆地查找所有比k大的数然后让其每个都减 $k$ 的和。

    树状数组即可胜任,复杂度 $O(nlogn)$ 。

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=2e5+5;
    inline int read(){
        int X=0,w=0;char ch=0;
        while(!isdigit(ch)){w|=ch=='-';ch=getchar();}
        while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
        return w?-X:X;
    }
    struct num{
        int w,id;
    }a[N],b[N],p[N];
    int sum[N],n,m;
    void msort(int l,int r){
        if(l>=r)return;
        int mid=(l+r)>>1;
        msort(l,mid);msort(mid+1,r);
        for(int i=l,j=l,k=mid+1;i<=r;i++){
            if(j<=mid&&(k>r||a[j].w<=a[k].w))b[i]=a[j++];
            else b[i]=a[k++],sum[b[i].id]+=mid-j+1;
        }
        for(int i=l;i<=r;i++)a[i]=b[i];
    }
    inline int lowbit(int t){return t&(-t);}
    struct tree{
        ll tr[N];
        tree(){memset(tr,0,sizeof(tr));}
        void add(int x,int y){
            for(int i=x;i<=n;i+=lowbit(i))tr[i]+=y;
            return;
        }
        ll qry(int x){
            ll res=0;
            for(int i=x;i>0;i-=lowbit(i))res+=tr[i];
            return res;
        }
    }T[2];
    int main(){
        n=read(),m=read();
        for(int i=1;i<=n;i++)p[i]=a[i]=(num){read(),i};
        
        msort(1,n);
        for(int i=1;i<=n;i++)T[0].add(sum[i]+1,1),T[1].add(sum[i]+1,sum[i]);
        
        while(m--){
            int t=read(),c=read();
            if(t==1){
                T[0].add(sum[c]+1,-1),T[1].add(sum[c]+1,-sum[c]);
                T[0].add(sum[c+1]+1,-1),T[1].add(sum[c+1]+1,-sum[c+1]);
                swap(sum[c],sum[c+1]);
                if(p[c].w<p[c+1].w)sum[c+1]++;
                if(p[c].w>p[c+1].w)sum[c]--;
                T[0].add(sum[c]+1,1),T[1].add(sum[c]+1,sum[c]);
                T[0].add(sum[c+1]+1,1),T[1].add(sum[c+1]+1,sum[c+1]);
                swap(p[c],p[c+1]);
            }else{
                c=min(c,n-1);
                printf("%lld
    ",T[1].qry(n)-T[1].qry(c+1)-(T[0].qry(n)-T[0].qry(c+1))*c);
            }
        }
        return 0;
    }

    +++++++++++++++++++++++++++++++++++++++++++

     +本文作者:luyouqi233。               +

     +欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/+

    +++++++++++++++++++++++++++++++++++++++++++

  • 相关阅读:
    夜空中最亮的星
    让我留在你身边
    反思
    又想起民谣那诗
    初学积性函数
    P1049 装箱问题(01背包)
    set
    紫书 习题 10-4 UVa 1644(素数筛)
    紫书 习题 10-2 UVa 808(建立坐标+找规律)
    紫书 习题 10-1UVa 111040(找规律)
  • 原文地址:https://www.cnblogs.com/luyouqi233/p/12435104.html
Copyright © 2011-2022 走看看