首页 > 其他分享 >LOJ #535 题解

LOJ #535 题解

时间:2023-01-12 10:36:53浏览次数:49  
标签:关键字 LOJ 题解 long int 535 逆序

问题转化为交换两个数,使排列的逆序对数最少。

设交换 \(a_i\) 和 \(a_j\) 且 \(i<j,a_i>a_j\)。则减小的逆序对数为

\[1+\sum_{k=i+1}^{j-1}[a_k<a_i]-[a_k>a_i]+[a_k>a_j]-[a_k<a_j]=1+2\sum_{k=i+1}^{j-1}[a_j<a_k<a_i] \]

显然最优者满足 \(a_i=\max_{k\le i}a_k,a_j=\min_{k\ge j}a_k\)。两者的可行集分别记为 \(A,B\)。

对于每个点 \((i,a_i)\),求出 \(A\) 中第一关键字更小,第二关键字更大者;\(B\) 中第一关键字更大,第二关键字更小者,得出能覆盖这个点的所有矩形。

则形成 \(n\) 个矩形,求覆盖最多的地方,扫描线。

#include<bits/stdc++.h>
using namespace std;
constexpr int N=3e5+5;
int n,h[N],A[N],B[N],totA,totB,xL[N<<1],xR[N<<1],yL[N<<1],yR[N<<1],dat[N<<3],tag[N<<3],c[N];
struct Opt{int L,R,val;};vector<Opt>op[N];
inline void add(int p){
	for(;p<=n;p+=p&-p)c[p]++;
}
inline int get(int p){
	int ret=0;for(;p;p^=p&-p)ret+=c[p];
	return ret;
}
inline void pushdown(int p){
	dat[p<<1]+=tag[p];dat[p<<1|1]+=tag[p];
	tag[p<<1]+=tag[p];tag[p<<1|1]+=tag[p];
	tag[p]=0;
}
inline void upd(int p,int l,int r,int L,int R,int x){
	if(L<=l&&r<=R)return dat[p]+=x,tag[p]+=x,void();
	pushdown(p);int mid=(l+r)>>1;
	if(L<=mid)upd(p<<1,l,mid,L,R,x);
	if(R>mid)upd(p<<1|1,mid+1,r,L,R,x);
	dat[p]=max(dat[p<<1],dat[p<<1|1]);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);cin>>n;long long S=0;
	for(int i=1;i<=n;i++){
		cin>>h[i];S+=i-get(h[i])-1;add(h[i]);
	}
	for(int i=1,mx=0;i<=n;i++)if(h[i]>mx)A[++totA]=i,mx=h[i];
	for(int i=n,mi=n+1;i;i--)if(h[i]<mi)B[++totB]=i,mi=h[i];
	reverse(B+1,B+totB+1);
	for(int i=1;i<=n;i++)xR[i]=lower_bound(A+1,A+totA+1,i)-A-1;
	for(int i=1;i<=n;i++)A[i]=h[A[i]];
	for(int i=1;i<=n;i++)xL[i]=upper_bound(A+1,A+totA+1,h[i])-A;
	for(int i=1;i<=n;i++)yL[i]=upper_bound(B+1,B+totB+1,i)-B;
	for(int i=1;i<=n;i++)B[i]=h[B[i]];
	for(int i=1;i<=n;i++)yR[i]=lower_bound(B+1,B+totB+1,h[i])-B-1;
	for(int i=1;i<=n;i++)if(xL[i]<=xR[i]&&yL[i]<=yR[i]){
		//printf("%d: x[%d,%d]; y[%d,%d]\n",i,xL[i],xR[i],yL[i],yR[i]);
		op[xL[i]].push_back({yL[i],yR[i],1});
		op[xR[i]+1].push_back({yL[i],yR[i],-1});
	}
	int ans=0;
	for(int i=1;i<=totA;i++){
		for(auto k:op[i])upd(1,1,totB,k.L,k.R,k.val);
		ans=max(ans,dat[1]);
	}
	cout<<S-ans*2<<endl;
	return 0;
}

标签:关键字,LOJ,题解,long,int,535,逆序
From: https://www.cnblogs.com/hihihi198/p/17045736.html

相关文章

  • AT2282 [ABC051C] Back and Forth 题解
    Description在一个平面直角坐标系内,有一点\(A(x_1,y_1)\)和点\(B(x_2,y_2)\)你需要从\(A\)点走到\(B\)点,再走到\(A\)点,再走到\(B\)点,再回到\(A\)点。期间,你......
  • P4198 楼房重建题解
    一道经典的线段树二分应用题目转化:把每个点换成斜率,此时发现,一个点能够被看见,当且仅当他本身就是前缀最大值用线段树维护单点修改,区间询问前缀最大值数量解题思路:要......
  • 2022SWJTU寒假选拔赛1题解
    目录A-马宝の皮颜矩阵I-小幻777J-小幻考考你A-马宝の皮颜矩阵Description给定矩阵\(a[N][M],1\leN·M\le1e5,1\lea[i][j]\le1e5\),求所有相同元素的曼哈顿......
  • 洛谷P6599 「EZEC-2」异或【题解】
    题目大意有\(T\)组数据,每组数据给定两个\(l,n\in\mathbb{N*}\),构造一个长为\(l\),每个元素不超过\(n\)的数组令他为\(a\),要使\[\sum_{i=1}^l\sum_{j=1}^{i-1}a_i\oplu......
  • SYUCT acm第八次限时训练题解
    SYUCTacm第八次限时训练题解MakeitBeautiful题目大意code#include<bits/stdc++.h>usingnamespacestd;constintN=100;inta[N];intb[N];voidsolve()......
  • 【题解】AT3611 Tree MST
    喝,长大了......
  • CF 1581B Diameter of Graph 题解
    题面:给定n个顶点,m条边,任意两点并且最大距离小于k,两个顶点只能连一条边,询问是否能构造出这样的图型思路:1.n=1时进行特判,只有k>1时成立2.m=n(n-1)/2时,是完全图,只有k......
  • 【题解】CF1268C K Integers
    萌新不懂就问,这是什么时代的题啊???思路trick题。首先根据trick可知:先将\([1,k]\)中的数聚在一起再排序是最优的。排序的花费是逆序对数,所以现在的问题是求把\([1,......
  • Codeforces 1278 F Cards 增强版 题解 (斯特林数,推式子)
    原题链接增强版链接增强版中k=1e7为啥网上题解的式子都那么长啊.jpg首先令\(p=\frac1m\)。求某个数的次幂的题通常都是无脑转下降幂:\(x^k=\sum_{i=0}^kS_2(k,i)x^{\u......
  • sloj bzoj2821. L的鞋子
    题目描述L是壕,他非常喜欢鞋子,他专门在他的别墅中修建了一个鞋柜,鞋柜是呈线性的,为了好找鞋子,他把他的鞋子分成了c种。虽然L没有小学毕业,但是对数字非常偏爱,他很忌讳奇数,因......