• [题解] LuoguP6185 [NOI Online 提高组]冒泡排序


    这是一道结论题......

    当你手玩几次冒泡过后,会发现一个非常有用的性质。

    下面令(c[i])表示第(i)个数前面有几个比他大的,那么逆序对的数量就是(sum_{i=1}^n c[i])

    考虑一次冒泡,所有(c[i])必定会减少(1),且只会减少(1)

    那么(k)次冒泡后原来小于等于(k)(c[i])都蒸发了,我们只要考虑在([k+1,n])这段区间里的(c[i]),答案就是

    [left(sumlimits_{k+1le c[i]} c[i] ight)-sumlimits_{c[i] ge k+1} k ]

    于是开两个树状数组维护一下就好了。

    交换操作的话分类讨论一下。

    #include <bits/stdc++.h>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;++i)
    #define per(i,a,n) for (int i=n-1;i>=a;--i)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define all(x) (x).begin(),(x).end()
    #define SZ(x) ((int)(x).size())
    typedef double db;
    typedef long long ll;
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    
    const int N=2e5+10;
    
    struct BIT {
        ll c[N]; int n;
    
        void init(int sz) {n=sz;rep(i,0,n+1) c[i]=0;}
    
        ll qwq(int x) {
            ll ans=0; for(;x;x-=x&-x) ans+=c[x];
            return ans;
        }
        ll qry(int l,int r) {return qwq(r)-qwq(l-1);}
        void upd(int x,ll v=1) {if(x!=0) for(;x<=n;x+=x&-x) c[x]+=v;}
    }bt[2];
    
    void upd(int x,int v=1) {bt[0].upd(x,v),bt[1].upd(x,v*x);}
    void qry(int l,int r,ll &c1,ll &c2) {c1=bt[0].qry(l,r),c2=bt[1].qry(l,r);}
    
    int n,m,a[N],cc[N];
    
    int main() {
    #ifdef LOCAL
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
    #endif
        scanf("%d%d",&n,&m);
        rep(i,1,n+1) scanf("%d",&a[i]);
        bt[0].init(n);
        rep(i,1,n+1) {
            cc[i]=i-bt[0].qwq(a[i])-1;
            bt[0].upd(a[i]);
        }
        bt[0].init(n),bt[1].init(n);
        rep(i,1,n+1) upd(cc[i]);
        while(m--) {
            int opt,x; scanf("%d%d",&opt,&x);
            if(opt==2) {
                if(x>=n) {puts("0");continue;}
                ll t1,t2;
                qry(x+1,n,t1,t2);
                printf("%lld
    ",t2-x*t1);
            } else {
                upd(cc[x],-1),upd(cc[x+1],-1);  // 先把贡献去掉
                if(a[x]>a[x+1]) --cc[x+1]; else ++cc[x]; // 分类讨论
                swap(cc[x],cc[x+1]),swap(a[x],a[x+1]);
                upd(cc[x],1),upd(cc[x+1],1);  // 再加回去
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【转】 UI自动化测试的关注点
    使用MapReduce将HDFS数据导入到HBase(一)
    Hadoop2.4.1 MapReduce通过Map端shuffle(Combiner)完成数据去重
    Hadoop2.4.1 使用MapReduce简单的数据清洗
    Hadoop2.4.1 64-Bit QJM HA and YARN HA + Zookeeper-3.4.6 + Hbase-0.98.8-hadoop2-bin HA Install
    hadoop2.2.0 MapReduce求和并排序
    hadoop2.2.0 MapReduce分区
    hadoop2.2.0伪分布模式64位安装
    hadoop2.2.0 MapReduce的序列化
    MyEclipse8.6下的svn插件安装
  • 原文地址:https://www.cnblogs.com/wxq1229/p/12434715.html
Copyright © 2020-2023  润新知