https://jzoj.net/senior/#main/show/3462
分成最少段就是分成极大段下降子串,这一步暴力完成,然后剩下的就是一个冒泡排序,统计逆序对即可。
复杂度O(nlogn)
#include<iostream> #include<cstdio> using namespace std; inline int rd(){ int ret=0,f=1;char c; while(c=getchar(),!isdigit(c))f=c=='-'?-1:1; while(isdigit(c))ret=ret*10+c-'0',c=getchar(); return ret*f; } const int MAXN=100005; int t[MAXN]; int n,val[MAXN],tot; int sta[MAXN],top; void update(int x,int w){ for(int i=x;i<=n;i+=i&-i) t[i]+=w; } int query(int x){ int ret=0; for(int i=x;i;i-=i&-i) ret+=t[i]; return ret; } int main(){ n=rd(); int x; long long ans=0; for(int i=1;i<=n;i++){ x=rd(); if(x<sta[top]){sta[++top]=x;continue;} while(top) val[++tot]=sta[top--]; sta[++top]=x;ans++; } while(top) val[++tot]=sta[top--]; for(int i=n;i>=1;i--) ans+=query(val[i]-1),update(val[i],1); cout<<ans; return 0; }