zoukankan      html  css  js  c++  java
  • [题解] 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;
    }
    
  • 相关阅读:
    【打印】windows打印控件,Lodop.js介绍
    【MySQL】MySQL查询数据库各表的行数
    【MySQL】MySQL中查询出数据表中存在重复的值list
    【php】php5.0以上,instanceof 用法
    日期转换:Cannot format given Object as a Date (SimpleDateFormat的parse和format)
    Groovy 正则表达式 匹配点号
    什么是开发框架
    SoapUI 增大使用内存
    Groovy API link
    Groovy 跳出each循环
  • 原文地址:https://www.cnblogs.com/wxq1229/p/12434715.html
Copyright © 2011-2022 走看看