• 洛谷 P3157 [CQOI2011]动态逆序对


    对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数。给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计整个序列的逆序对数。

    可以值域分块,块套树状数组,树套树

    不过用序列分块(+vector)一样能水过这道题

    考虑删去一个点(x)对答案产生的影响,拿下面的数列来说

    [1,2……x……n-1,n ]

    对于区间([1,x-1])(a_i>a_x)会产生逆序对

    对于区间([x+1,n])(a_i<a_x)会产生逆序对

    那么每次删点后统计一下(x)两侧满足条件的数就好了

    我们对序列分块,同一个块里的用(vector)排好序,和(x)在不同块的二分查找更新答案,和(x)在同一个块的暴力枚举更新答案,每次删点的时候在(vector)里删除点就好了

    复杂度大约是(O(Mlog(N)sqrt{N})),吸吸氧就过了

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #define N 100000
    #define rep(i,s,t) for (register int i=s;i<=t;i++)
    #define drep(i,s,t) for (register int i=t;i>=s;i--)
    #define il inline
    using namespace std;
    int n,m,a[N+5],data[N+5],bs,blo[N+5],L[N+5],R[N+5],na[N+5],d[N+5],id[N+5],cnt;
    long long ans;
    vector <int> p[N+5];
    void merge_sort(int l,int r)
    {
        if (r-l>0)
        {
            int it=l,mid=l+r>>1,p=l,q=mid+1;
            merge_sort(l,mid);
            merge_sort(mid+1,r);
            while (p<=mid||q<=r)
            {
                if (q>r||p<=mid&&data[p]<=data[q])
                    na[it++]=data[p++];
                else
                {
                    na[it++]=data[q++];
                    ans+=(long long)mid-p+1;
                }
            }
            rep(i,l,r)
                data[i]=na[i];
        }
    }
    il void del(int x)
    {
        d[x]=1;
        vector <int>::iterator it=lower_bound(p[blo[x]].begin(),p[blo[x]].end(),a[x]);
        p[blo[x]].erase(it);
    }
    il void calc(int x)
    {
        rep(i,1,blo[x]-1)
            ans-=(long long)(p[i].end()-upper_bound(p[i].begin(),p[i].end(),a[x]));
        rep(i,L[blo[x]],x-1)
            if (a[i]>a[x]&&!d[i])
                ans--;
        rep(i,x+1,R[blo[x]])
            if (a[i]<a[x]&&!d[i])
                ans--;
        rep(i,blo[x]+1,blo[n])
            ans-=(long long)(lower_bound(p[i].begin(),p[i].end(),a[x])-p[i].begin());
    }
    il int read()
    {
    	int X(0),w(0);char ch(0);
    	while (!isdigit(ch))w|=ch=='-',ch=getchar();
    	while (isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    	return w?-X:X;
    }
    int main()
    {
        n=read();
        m=read();
        bs=sqrt(n);
        rep(i,1,n)
        {
            a[i]=read();
            data[i]=a[i];
            id[a[i]]=++cnt;
            blo[i]=(i-1)/bs+1;
            if (!L[blo[i]])
                L[blo[i]]=i;
            R[blo[i]]=i;
            p[blo[i]].push_back(a[i]);
        }
        merge_sort(1,n);
        rep(i,1,blo[n])
            sort(p[i].begin(),p[i].end());
        int x;
        rep(i,1,m)
        {
            printf("%lld
    ",ans);
            x=read();
            del(id[x]);
            calc(id[x]);
        }
        return 0;
    }
    
  • 相关阅读:
    JS 格林威治时间格式(GMT)格式化
    SQL Server各个版本功能比较
    SQL Server各个版本功能比较
    SQL Server各个版本功能比较
    SQLl中的left join、right join、inner join详解
    SQLl中的left join、right join、inner join详解
    SQLl中的left join、right join、inner join详解
    【必备】jQuery性能优化的38个建议
    Metasploit笔记
    SpringBoot开发二十-Redis入门以及Spring整合Redis
  • 原文地址:https://www.cnblogs.com/sdlang/p/13068080.html
Copyright © 2020-2023  润新知