lojnode
给你一个排列$h_i$,你须要交换任意两个位置上的数使得交换后排列的逆序对数最少。 $n \le 3\times 10^5$spa
首先能够发现,若是交换两个位置$i,j(h_i>h_j)$,那么逆序对数的减少量就是知足$i<k<j$且$h_j<h_k<h_i$的$k$的数量乘$2$。这至关于一个二维数点的问题。 理性分析一下,枚举出来的$i$必定是前缀最大值,$j$必定是后缀最小值,否则这个矩形内包含的点的数量必定不是最多的。 那么咱们就构造出了一个知足前缀最大的集合$U$和一个知足后缀最小的集合$D$,如今要从两个集合中各选出一个构成一个矩形,最大化其中的点数。注意这两个集合中的$h_i$都是单调递增的。 咱们考虑每个点$(x,h_x)$会出如今哪些矩形中。 在$U$中二分找到最小的$l$知足$h_l>h_x$,在$D$中二分找到最小的$r$知足$h_r<h_x$,那么要使点$(x,h_x)$被包含在$(i,j)$构成的矩形内部的条件就是:$i\in[l,x-1],j\in[x+1,r]$。 把点转化为矩阵,问题变成求矩形覆盖的最大值,线段树维护扫描线便可。 复杂度$O(n\log n)$。code
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; int gi(){ int x=0,w=1;char ch=getchar(); while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if (ch=='-') w=0,ch=getchar(); while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar(); return w?x:-x; } const int N = 3e5+5; int n,h[N],s1[N],t1,s2[N],t2,ins[N],cnt,mx[N<<2],tag[N<<2],c[N],ans; long long sum; struct node{ int y,x1,x2,op; bool operator < (const node &b) const{ if (y==b.y) return op<b.op; return y<b.y; } }p[N<<1]; int binary1(int x){ int l=1,r=t1,res=0; while (l<=r){ int mid=l+r>>1; if (h[s1[mid]]>h[x]) res=mid,r=mid-1; else l=mid+1; } return s1[res]; } int binary2(int x){ int l=1,r=t2,res=0; while (l<=r){ int mid=l+r>>1; if (h[s2[mid]]<h[x]) res=mid,r=mid-1; else l=mid+1; } return s2[res]; } void modify(int x,int l,int r,int ql,int qr,int v){ if (l>=ql&&r<=qr) {mx[x]+=v;tag[x]+=v;return;} int mid=l+r>>1; if (ql<=mid) modify(x<<1,l,mid,ql,qr,v); if (qr>mid) modify(x<<1|1,mid+1,r,ql,qr,v); mx[x]=max(mx[x<<1],mx[x<<1|1])+tag[x]; } void mdf(int k){while(k<=n)++c[k],k+=k&-k;} int qry(int k){int s=0;while(k)s+=c[k],k-=k&-k;return s;} int main(){ n=gi(); for (int i=1;i<=n;++i) h[i]=gi(); for (int i=1;i<=n;++i) if (i==1||h[i]>h[s1[t1]]) s1[++t1]=i,ins[i]=1; for (int i=n;i>=1;--i) if (i==n||h[i]<h[s2[t2]]) s2[++t2]=i,ins[i]=1; for (int i=1;i<=n;++i){ if (ins[i]) continue; int l=binary1(i),r=binary2(i); if (l<i&&i<r){ p[++cnt]=(node){i+1,l,i-1,1}; p[++cnt]=(node){r+1,l,i-1,-1}; } } sort(p+1,p+cnt+1); for (int i=1;i<=cnt;++i){ modify(1,1,n,p[i].x1,p[i].x2,p[i].op); if (p[i].y!=p[i+1].y) ans=max(ans,mx[1]); } for (int i=n;i;--i) sum+=qry(h[i]-1),mdf(h[i]); printf("%lld\n",sum-2*ans); return 0; }