time

  考虑一个数要么在左边构成顺序列,要么在右边构成逆序列。
  两者的代价是他与他左边的数构成的逆序对个数以及他与他右边的数所构成的顺序对数。
  两者取最小值。
  累加。
  输出。
  AC。。。。。。
  为什么我考场上没有想到啊。。。。。。。。。FAF。

代码
#include<bits/stdc++.h>
using namespace std;
namespace STD
{
	#define rr register
	#define fi first
	#define se second
	typedef long long ll;
	typedef pair<int,int> pp;
	const int N=1e5+4;
	const int inf=INT_MAX;
	int n,ans,maxn;
	int a[N];
	int l[N],r[N];
	int read()
	{
		rr int x_read=0,y_read=1;
		rr char c_read=getchar();
		while(c_read<'0'||c_read>'9')
		{	
			if(c_read=='-') y_read=-1;
			c_read=getchar();
		}
		while(c_read<='9'&&c_read>='0')
		{
			x_read=(x_read<<3)+(x_read<<1)+(c_read^48);
			c_read=getchar();
		}
		return x_read*y_read;
	}	
	class tree_a
	{
		private:
			int t[N];
			inline int lowbit(int x){return x&(-x);}
		public:
			int ask(int,int);
			void insert(int);
			void clear(){memset(t,0,sizeof t);}
	}t;
	int tree_a::ask(int l,int r)
	{
		int ret=0;
		while(r)
		{
			ret+=t[r];
			r-=lowbit(r);
		}
		while(l)
		{
			ret-=t[l];
			l-=lowbit(l);
		}
		return ret;
	}
	void tree_a::insert(int val)
	{
		while(val<=maxn)
		{
			t[val]++;
			val+=lowbit(val);
		}
	}
};
using namespace STD;
int main()
{
	n=read();
	for(rr int i=1;i<=n;i++) a[i]=read(),maxn=max(maxn,a[i]);
	for(rr int i=1;i<=n;i++)
	{
		l[i]=t.ask(a[i],maxn);
		t.insert(a[i]);
	}
	t.clear();
	for(rr int i=n;i>=1;i--)
	{
		r[i]=t.ask(a[i],maxn);
		t.insert(a[i]);
	}
	for(rr int i=1;i<=n;i++)
		ans+=min(l[i],r[i]);
	printf("%d\n",ans);
}
posted @ 2021-08-06 19:35  Geek_kay  阅读(13)  评论(0编辑  收藏  举报