LOJ535「LibreOJ Round #6」花火

LOJ535「LibreOJ Round #6」花火

不难发现最小交换次数就是你逆序对数

哪次用这个随便交换和答案无关,我们考虑第一次用

暴力就是 \(O(n^2\log n)\)

直接枚举点对 \((i,j)\,[a_i \lt a_j][i \lt j]\)

能减少的逆序对数就是 \(2\) 倍,\([i+1,j-1]\) 区间内 \([a_j+1,a_i-1]\) 的个数

这个证明显然 \([1,i-1]\;[j+1,n]\) 都无影响,\([i,j]\) 不用考虑比 \(a_i\) 大的数,比 \(a_j\) 小的数,剩下的推下即可

考虑降到 \(O(n\log n)\)

不妨把每个点放到一个平面直角坐标系上!!!

类似下图这种情况,枚举矩形两角,求包含点数最多的矩形包含的点数

image

我们考虑如何 \(O(n\log n)\) 内求答案

对于下图这种情况,\(C\)\(A\) 更优

image

\(E\)\(C\) 更优

image

则被选择的左上角和右下角一定形似

image

这个预处理 \(O(n)\),可以单调栈也可以维护左侧最大值和右侧最小值,证明显然,如左侧只要下降,肯定不如之前上升的峰值的点

我们记这些点形成的序列为 \(L\;R\)

没法枚举矩形,但我们可以枚举点

这个点对哪些矩形产生贡献?左上方的点(矩阵左上角),右下方的点(矩阵右下角)这样的组合方案有贡献

这样的点数 \(L\) \(R\) 上一段连续的点,设左上方最左侧能成为左端点的点为 \(l\) 右端点为 \(r\)

这只要矩形两角在 \([l,i-1]\)\([i+1,r]\) 区间内的,都对矩形有贡献

image

image

矩形不好计算,我们考虑再次对 \(L\)\(R\) 建立平面直角坐标系

则用点对 \((x,y)\) 表述左上角在 \(x\) 右下角在 \(y\) 的矩形

则这个点产生的贡献作用在 \((l\sim i-1,i+1 \sim r)\) 内的点

转化为 \(L\;R\) 坐标系内,求一个点被矩形包含数量的最大值

二维点求最大矩形数,扫描线即可

const int N=3e5+10;
int n,ans,res;
int a[N],mxl[N],mnr[N];
struct Oper{int l,r,x;};
vector<Oper> op[N];

struct Bit{
	int s[N];
	void add(int i,int x){for(;i<=n;i+=i&(-i)) s[i]+=x;}
	int query(int i)
	{
		int res=0;
		for(;i;i-=i&(-i)) res+=s[i];
		return res;
	}
}bit;

struct Seg{
	struct node{
		int l,r;
		int maxt,add;
	}tr[N*4];
	
	void chf(int idx)
	{
	    node &t=tr[idx],&ls=tr[idx<<1],&rs=tr[idx<<1|1];
	    t.maxt=max(ls.maxt,rs.maxt);
	}
	
	void chs(int idx)
	{
	    node &t=tr[idx],&ls=tr[idx<<1],&rs=tr[idx<<1|1];
	    if(t.add)
	    {
			ls.add+=t.add,rs.add+=t.add;
		    ls.maxt+=t.add,rs.maxt+=t.add;
		    t.add=0;
		}
	}
	
	void build(int l,int r,int idx)
	{
	    tr[idx]={l,r};
	    if(l==r) return;
	    int mid=(l+r)>>1;
	    build(l,mid,idx<<1);
	    build(mid+1,r,idx<<1|1);
	    chf(idx);
	}
	
	void modify(int ql,int qr,int idx,int x)
	{
	    node &t=tr[idx];
	    if(ql<=t.l && qr>=t.r)
	    {
	        t.add+=x,t.maxt+=x;
	        return;
	    }
	    
	    chs(idx);
	    int mid=(t.l+t.r)>>1;
	    if(ql<=mid) modify(ql,qr,idx<<1,x);
	    if(qr>mid) modify(ql,qr,idx<<1|1,x);
	    chf(idx);
	}
}seg;

signed main()
{
	n=fr();
	for(int i=1;i<=n;i++) a[i]=fr();
	for(int i=1;i<=n;i++) mxl[i]=max(mxl[i-1],a[i]);
	mnr[n]=a[n];
	for(int i=n-1;i;i--) mnr[i]=min(mnr[i+1],a[i]);
	
	for(int i=1;i<=n;i++)
		res+=bit.query(n)-bit.query(a[i]),bit.add(a[i],1);
	
	for(int i=1;i<=n;i++)
	{
		int l=lower_bound(mxl+1,mxl+i,a[i])-mxl;
		int r=lower_bound(mnr+i,mnr+n+1,a[i])-mnr;
		if(l<i && r>i) op[l].pb({i+1,r,1}),op[i].pb({i+1,r,-1});
	}
	
	seg.build(1,n,1);
	for(int i=1;i<=n;i++)
	{
		for(auto v:op[i]) seg.modify(v.l,v.r,1,v.x);
		ans=max(ans,seg.tr[1].maxt);
	}
	fw(res-(ans<<1));

	return 0;
}
posted @ 2023-07-13 08:13  xyzfrozen  阅读(28)  评论(0)    收藏  举报