• bzoj2141_排队


    题意

    给定(n)个数,每次交换两个数,输出交换后的逆序数。

    分析

    • 交换两个数只会影响到对应区间内的逆序数,具体为减少区间([l+1,r-1])中比(a[r])大的数的个数,增加比(a[r])大的数的个数,减少比大的数的个数,(a[l])增加比(a[l])小的数的个数。
    • 转化为单点修改+查询区间值域个数,树套树。
    • 思路不难想,写完调了一年,注意几个点
      • 外层bit大小是的是序列长度n,不是离散化后的值域ns。
      • 数据不保证(l<=r)
      • 注意相同元素。
      • 最后要判断(a[l])(a[r])的大小关系,除去相等。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=2e4+50;
    int n,ns,m,a[N],l,r,tr[N*20],x[N],y[N],c1,c2;
    struct Orz{
        vector<int> a;
        void init(){
            a.clear();
        }
        int siz(){
            return a.size();
        }
        void add(int x){
            a.push_back(x);
        }
        void work(){
            sort(a.begin(),a.end());
            a.erase(unique(a.begin(),a.end()),a.end());
        }
        int idx(int v){
            return lower_bound(a.begin(),a.end(),v)-a.begin()+1;
        }
        int val(int i){
            return a[i-1];
        }
    }orz;
    struct HJT{
    #define mid (l+r)/2
        int tot,sum[N*200],ls[N*200],rs[N*200];
        void update(int &x,int l,int r,int v,int add){
            if(!x){
                x=++tot;
            }
            sum[x]+=add;
            if(l<r){
                if(v<=mid){
                    update(ls[x],l,mid,v,add);
                }else{
                    update(rs[x],mid+1,r,v,add);
                }
            }
        }
        int query(int l,int r,int k){
            if(k==0){
                return 0;
            }
            if(r<=k){
                int ans=0;
                for(int i=1;i<=c1;i++){
                    ans-=sum[x[i]];
                }
                for(int i=1;i<=c2;i++){
                    ans+=sum[y[i]];
                }
                return ans;
            }
            if(k<=mid){
                for(int i=1;i<=c1;i++){
                    x[i]=ls[x[i]];
                }
                for(int i=1;i<=c2;i++){
                    y[i]=ls[y[i]];
                }
                return query(l,mid,k);
            }else{
                int ans=0;
                for(int i=1;i<=c1;i++){
                    ans-=sum[ls[x[i]]];
                }
                for(int i=1;i<=c2;i++){
                    ans+=sum[ls[y[i]]];
                }
                for(int i=1;i<=c1;i++){
                    x[i]=rs[x[i]];
                }
                for(int i=1;i<=c2;i++){
                    y[i]=rs[y[i]];
                }
                return ans+query(mid+1,r,k);
            }
        }
    }ac;
    struct BIT{
        int lowbit(int x){
            return x&(-x);
        }
        void modify(int i,int x){
            int k=a[i];
            while(i<=n){
                ac.update(tr[i],1,ns,k,x);
                i+=lowbit(i);
            }
        }
        int query(int l,int r,int xi,int yi){
            if(xi>yi){
                return 0;
            }
            c1=c2=0;
            for(int i=l-1;i;i-=lowbit(i)){
                x[++c1]=tr[i];
            }
            for(int i=r;i;i-=lowbit(i)){
                y[++c2]=tr[i];
            }
            int R=ac.query(1,ns,yi);
            c1=c2=0;
            for(int i=l-1;i;i-=lowbit(i)){
                x[++c1]=tr[i];
            }
            for(int i=r;i;i-=lowbit(i)){
                y[++c2]=tr[i];
            }
            int L=ac.query(1,ns,xi-1);
            return R-L;
        }
    }bit;
    int main(){
        // freopen("in.txt","r",stdin);
        scanf("%d",&n);
        orz.init();
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            orz.add(a[i]);
        }
        orz.work();
        ns=orz.siz();
        int ans=0;
        for(int i=1;i<=n;i++){
            a[i]=orz.idx(a[i]);
            bit.modify(i,1);
            ans+=bit.query(1,i,a[i]+1,ns);
        }
        printf("%d
    ",ans);
        scanf("%d",&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&l,&r);
            if(l>r){
                swap(l,r);
            }
            if(l==r){
                printf("%d
    ",ans);
                continue;
            }
            if(r-l>=2){
                int ta=bit.query(l+1,r-1,a[r]+1,ns);
                int tb=bit.query(l+1,r-1,a[l]+1,ns);
                int tc=bit.query(l+1,r-1,1,a[r]-1);
                int td=bit.query(l+1,r-1,1,a[l]-1);
                ans-=ta;
                ans+=tc;
                ans+=tb;
                ans-=td;
            }
            if(a[l]<a[r]){
                ans++;
            }else if(a[l]>a[r]){
                ans--;
            }
            bit.modify(l,-1);
            bit.modify(r,-1);
            swap(a[l],a[r]);
            bit.modify(l,1);
            bit.modify(r,1);
            printf("%d
    ",ans);
        }
        return 0;
    }
    
  • 相关阅读:
    Toast的替代者Snackbar
    SnappyDB—Android上的NoSQL数据库简介
    ButterKnife使用小结
    The following classes could not be found:
    asp.net后台解析JSON,并将值赋给对象
    .NET4.0的listview与DataPager的结合使用时的模板编辑
    ASP.NET 后台页面无法识别服务器控件ID
    Asp.net中判断是否是指定页面请求的代码示例
    ASP.NET中修改从数据库获取的datatable中的值
    GridView自定义分页样式(上一页,下一页,到第几页)
  • 原文地址:https://www.cnblogs.com/zxcoder/p/11503684.html
Copyright © 2020-2023  润新知