zoukankan      html  css  js  c++  java
  • [NOI Online #1 提高组] 冒泡排序

    Description

    给定一个 (1 ∼ n) 的排列 (p_i),接下来有 (m) 次操作,操作共两种:

    1. 交换操作:给定 (x),将当前排列中的第 (x) 个数与第 (x+1) 个数交换位置。
    2. 询问操作:给定 (k),请你求出当前排列经过 (k) 轮冒泡排序后的逆序对个数。

    Solution

    (c[i]) 表示数 (i) 前有几个比它大的

    在一次冒泡排序中,所有非零的 (c[i]) 都减少 (1)

    于是经过 (k) 次冒泡排序后的逆序数就是

    [sum_{c[i]>k} (c[i]-k)=sum_{c[i]>k} c[i]- ksum_{c[i]>k} 1 ]

    开两个树状数组,(s[k],t[k]) 分别维护对 (c[i]=k) 时的 (sum c[i])(sum 1)

    修改时,若 (a[x]<a[x+1]) 则交换后 (c[a[x]]+1)(这里的 (a[]) 是交换前的),反之 (c[a[x+1]]-1)

    #include <bits/stdc++.h>
    
    using namespace std;
    
    #define int long long
    
    const int N = 200005;
    
    struct bitree
    {
        int ar[N];
        int lowbit(int t)
        {
            return t & (-t);
        }
        void add(int i, int v)
        {
            ++i;
            for (; i < N; ar[i] += v, i += lowbit(i));
        }
        int sum(int i)
        {
            int s = 0;
            for (; i > 0; s += ar[i], i -= lowbit(i));
            return s;
        }
        int query(int l,int r)
        {
            return sum(r+1)-sum(l);
        }
    } s,t,b;
    
    int n,m,a[N],c[N],t1,t2;
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin>>n>>m;
        for(int i=1; i<=n; i++) cin>>a[i];
        for(int i=1; i<=n; i++)
        {
            c[a[i]]=b.query(a[i]+1,n);
            b.add(a[i],1);
        }
        for(int i=1; i<=n; i++)
        {
            s.add(c[i],c[i]);
            t.add(c[i],1);
        }
        while(m--)
        {
            cin>>t1>>t2;
            int x=t2;
            if(t1==1)
            {
                s.add(c[a[x]],-c[a[x]]);
                t.add(c[a[x]],-1);
                s.add(c[a[x+1]],-c[a[x+1]]);
                t.add(c[a[x+1]],-1);
                if(a[x]<a[x+1])
                {
                    c[a[x]]++;
                }
                else
                {
                    c[a[x+1]]--;
                }
                swap(a[x],a[x+1]);
                s.add(c[a[x]],c[a[x]]);
                t.add(c[a[x]],+1);
                s.add(c[a[x+1]],c[a[x+1]]);
                t.add(c[a[x+1]],+1);
            }
            else
            {
                t2=min(t2,n);
                cout<<s.query(t2+1,n)-t2*t.query(t2+1,n)<<endl;
            }
        }
    }
    
    
  • 相关阅读:
    vue 如何点击按钮返回上一页
    vue遍历数组和对象的方法以及他们之间的区别
    css隐藏滚动条
    DOM编程以及domReady加载的几种方式
    修改默认滚动条默认样式
    面试题集锦
    正则表达式
    闭包及应用以及顺序处理ajax请求
    实现自己的(模仿jquery)toggle函数
    Asp.Net与SEO Viewstate优化终极解决方案
  • 原文地址:https://www.cnblogs.com/mollnn/p/13199806.html
Copyright © 2011-2022 走看看