• luogu1975 [国家集训队]排队


    思路

    序列中

    i 1 2 3 4 5 6 7 8 9 10
    a[i] a b c L d e f R g h

    现逆序对为ans,要交换L,R
    ([1,3],[9,10])这两段区间的都不会被他俩影响 (因为L,R和他们相对位置没变啦)
    所以现在我们只需要考虑区间([4,8])就好,其他的不考虑在内
    一个数对一个区间产生逆序对的贡献为
    ① 前面大于他的数的个数 (在区间前面)
    ② 后面小于他的数的个数 (在区间后面)
    因为(L,R)之间的区间3,6是不变的(废话)
    (L,R)又在区间两端
    那么很显然的
    (ans=ans-(L对区间zz的贡献②)+(L对区间zz的贡献①)-(R对区间zz的贡献①)+(R对区间zz的贡献②))
    那区间内的贡献咋求啊?
    定义不是很明确了吗 就是区间大于x或者小于的个数
    (=>ans-(区间zz内小于L的个数)+(区间zz内大于L的个数)-(区间zz内大于R的个数)+(区间zz内小于R的个数))(注意,相等的没有任何贡献)
    无脑数据结构呗
    随便来个带修主席树 (树状数组套线段树)
    复杂度(nlog^{2}n)
    但常数巨大,更新一次ans要询问8次

    错误

    都是些zz错误
    n写成len
    特盘忘记输出ans

    代码

    //天苍苍,野茫茫,代码怎么这么长
    #include <bits/stdc++.h>
    #define FOR(i,a,b) for(int i=a;i<=b;++i)
    using namespace std;
    const int maxn=1e5+7;
    int read() {
        int x=0,f=1;char s=getchar();
        for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
        for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
        return x*f;
    }
    int n,m,ans,len,rt[maxn],a[maxn],lsh[maxn],cnt;
    int thu[maxn];
    struct node {
        int ch[2],siz;
    }e[maxn*30];
    void build(int &now,int old,int l,int r,int k) {
         now=++cnt;
         e[now]=e[old];
         e[now].siz++;
         if(l==r) return;
         int mid=(l+r)>>1;
         if(k<=mid) build(e[now].ch[0],e[old].ch[0],l,mid,k);
         else build(e[now].ch[1],e[old].ch[1],mid+1,r,k);
    }
    void modify(int &now,int l,int r,int k,int gs) {
        if(!now) now=++cnt;
        e[now].siz+=gs;
        if(l==r) return;
        int mid=(l+r)>>1;
        if(k<=mid) modify(e[now].ch[0],l,mid,k,gs);
        else modify(e[now].ch[1],mid+1,r,k,gs);
    }
    int query1(int now,int l,int r,int k) { //小于mid的数 
        if(l>=k) return 0;
        if(r<k) {
            int tot=e[now].siz;
            FOR(i,1,thu[0]) tot+=e[thu[i]].siz;
            return tot;
        }
        int mid=(l+r)>>1;
        if(k<=mid) {
            FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[0];
            return query1(e[now].ch[0],l,mid,k);	
        } else {
            int tot=e[e[now].ch[0]].siz;
            FOR(i,1,thu[0]) tot+=e[e[thu[i]].ch[0]].siz;
            FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[1];
            return tot+query1(e[now].ch[1],mid+1,r,k);	
        }
    }
    int query2(int now,int l,int r,int k) { //大于mid的数 
        if(r<=k) return 0;
        if(l>k) {
            int tot=e[now].siz;
            FOR(i,1,thu[0]) tot+=e[thu[i]].siz;
            return tot;
        }
        int mid=(l+r)>>1;
        if(k<=mid) {
            int tot=e[e[now].ch[1]].siz;
            FOR(i,1,thu[0]) tot+=e[e[thu[i]].ch[1]].siz;
            FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[0];
            return tot+query2(e[now].ch[0],l,mid,k);
        } else {
            FOR(i,1,thu[0]) thu[i]=e[thu[i]].ch[1];
            return query2(e[now].ch[1],mid+1,r,k);	
        }
    }
    int solve(int l,int r,int k,int pd) {//区间内小于(或小于)k的个数
        int tmp=0;
        
        thu[0]=0;
        for(int i=r;i>=1;i-=(i&-i)) thu[++thu[0]]=rt[i+n];
        tmp+=pd ? query1(rt[r],1,len,k) : query2(rt[r],1,len,k);
        
        thu[0]=0;
        for(int i=l-1;i>=1;i-=(i&-i)) thu[++thu[0]]=rt[i+n];
        tmp-=pd ? query1(rt[l-1],1,len,k) : query2(rt[l-1],1,len,k);
        
        return tmp;
    }
    namespace get_init_ans {
        int sum[maxn];
        void BIT_modify(int x) {
            for(int i=x;i<=n;i+=(i&-i)) sum[i]++;
        }
        int BIT_query(int x) {
            int tot=0;
            for(int i=x;i>=1;i-=(i&-i)) tot+=sum[i];
            return tot;
        } 
        void get_ans() {
            for(int i=1;i<=n;++i) {
                BIT_modify(a[i]); 
                ans+=i-BIT_query(a[i]);
            }
        }
    }
    using namespace get_init_ans; 
    int main() {
        //read
        n=read();
        FOR(i,1,n) a[i]=lsh[i]=read();
        //lsh and init
        sort(lsh+1,lsh+1+n);
        len=unique(lsh+1,lsh+1+n)-lsh-1;
        FOR(i,1,n) {
            a[i]=lower_bound(lsh+1,lsh+1+len,a[i])-lsh;	
            build(rt[i],rt[i-1],1,len,a[i]);
        }
        //get_ans
        get_ans();
        cout<<ans<<"
    ";
        //work
        m=read();
        FOR(i_ak_ioi,1,m) {
            int x=read(),y=read(),l,l1=0,l2=0,r,r1=0,r2=0;
            if(a[x]==a[y]) {
                cout<<ans<<"
    ";
                continue;   
            }
            if(x>y) swap(x,y);
            //query
            l=x+1,r=y-1;
            if(l<=r) {
                l2=solve(l,r,a[x],1);
                l1=solve(l,r,a[x],0);
                r2=solve(l,r,a[y],1);
                r1=solve(l,r,a[y],0);
            }
            //update
            ans=ans-l2+l1-r1+r2+(a[x]<a[y] ? 1 : -1);
            cout<<ans<<"
    ";
            //update
            for(int i=x;i<=n;i+=(i&-i)) {
                modify(rt[i+n],1,len,a[x],-1);
                modify(rt[i+n],1,len,a[y],1);
            }
            for(int i=y;i<=n;i+=(i&-i)) {
                modify(rt[i+n],1,len,a[y],-1);
                modify(rt[i+n],1,len,a[x],1);	
            }
            swap(a[x],a[y]);
        }
        return 0;
    }
    
  • 相关阅读:
    C#动态调用webservice方法
    WinForm客户端调用 WebService时 如何启用Session
    C# 调用 Web Service 时出现 : 407 Proxy Authentication Required错误的解决办法
    ms sql 在任何位置 添加列
    Python requests
    LookupError: unknown encoding: cp65001
    [转]HTTP请求模型和头信息参考
    【原】使用StarUML画用例图
    【微信转载】Google是如何做测试的
    手机SD卡损坏补救措施
  • 原文地址:https://www.cnblogs.com/dsrdsr/p/10121541.html
Copyright © 2020-2023  润新知