【DS】loj#535. 「LibreOJ Round #6」花火

题传

真难写,,

考虑冒泡排序,每一次交换相邻的减少 1 对逆序对,那么我们肯定要第二种操作尽量多地减少逆序对。

考虑第二种操作 swap(i,j) 减少的逆序对数量:k(i,j),hj<hk<hik 的个数乘二。

考虑抽象到二维平面,点坐标为 (i,hi),那么就是以 (i,hi) 为左上角,(j,hj) 为右下角的矩形内部点数量。

但这样暴力算还是 O(n2logn)

看看选择的点有什么性质。

自己画画图,既然 i 为左上角,那么 i 应该是单增的,所以应该选择的是前缀最大值的点。

这时候可能有小可爱跟我一样 SB,想了好久 j 是前缀最小值还是后缀最小值。

黑色的是前缀最大值的点,红色是前缀最小值,蓝色是后缀最小值。

然后我思考了很久发现不知道选择是前缀还是后缀。

事实上图画错了!

所以显然是右端点是后缀最小值的点。

这样暴力维护也没用,找找性质,枚举右端点?可惜左端点并不单增。

考虑正难则反,让 k 去贡献每对 (i,j),即每个矩形。

需要满足的是 i<k,hi>hk,j>k,hj<hk,发现因为连续区间且维护的前缀最大、后缀最小都单调,因此二分找出合法区间,变成二维平面矩形加、点最大值。扫描线即可。

//swap(i,j)-> -= i<k<j ,a[i]>a[k],a[j]<a[k],a[j]<a[k]<a[i] //二维平面(i,a[i]),矩形查 #include <bits/stdc++.h> #define int long long #define pb push_back using namespace std; #define N (int)(3e5+5) int n,a[N],sum[N]; int lowbit(int x) { return x&(-x); } void add(int x,int v) { while(x<=n) sum[x]+=v,x+=lowbit(x); } int qry(int x) { int res=0; while(x) res+=sum[x],x-=lowbit(x); return res; } namespace zzx { int Ls[N*32],Rs[N*32],sum[N*32],rt[N],tot=0; void update(int pre,int &cur,int l,int r,int pos) { if(!cur) cur=++tot; sum[cur]=sum[pre]+1; if(l==r) return ; int mid=(l+r)>>1; if(pos<=mid) Rs[cur]=Rs[pre],update(Ls[pre],Ls[cur],l,mid,pos); else Ls[cur]=Ls[pre],update(Rs[pre],Rs[cur],mid+1,r,pos); } int query(int pre,int cur,int l,int r,int cl,int cr) { if(cl>cr) return 0; int qwq=sum[cur]-sum[pre]; if(cl<=l&&r<=cr) return qwq; int mid=(l+r)>>1,res=0; if(cl<=mid) res=query(Ls[pre],Ls[cur],l,mid,cl,cr); if(cr>mid) res+=query(Rs[pre],Rs[cur],mid+1,r,cl,cr); return res; } } using namespace zzx; vector<int>L,R; struct node { int l,r,v; node() { } node(int nl,int nr,int nv) { l=nl; r=nr; v=nv; } }; vector<node>p[N]; namespace XDS { #define ls (cur<<1) #define rs (ls|1) int mx[N<<2],tag[N<<2]; void push_up(int cur) { mx[cur]=max(mx[ls],mx[rs]); } void push_down(int cur) { if(tag[cur]==0) return ; mx[ls]+=tag[cur]; mx[rs]+=tag[cur]; tag[ls]+=tag[cur]; tag[rs]+=tag[cur]; tag[cur]=0; } void update(int cur,int l,int r,int cl,int cr,int x) { if(cl<=l&&r<=cr) { mx[cur]+=x; tag[cur]+=x; return ; } push_down(cur); int mid=(l+r)>>1; if(cl<=mid) update(ls,l,mid,cl,cr,x); if(cr>mid) update(rs,mid+1,r,cl,cr,x); push_up(cur); } int query(int cur,int l,int r,int cl,int cr) { if(cl<=l&&r<=cr) { // cout<<mx[cur]<<'\n'; return mx[cur]; } push_down(cur); int mid=(l+r)>>1,res=0; if(cl<=mid) res=query(ls,l,mid,cl,cr); if(cr>mid) res=max(res,query(rs,mid+1,r,cl,cr)); return res; } } using namespace XDS; bool vis[N]; signed main() { //freopen("columns9_3.in","r",stdin); cin.tie(0); std::ios::sync_with_stdio(false); cin>>n; int ans=0; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=n;i++) { ans+=qry(n)-qry(a[i]); add(a[i],1); } for(int i=1;i<=n;i++) update(rt[i-1],rt[i],1,n,a[i]); // cout<<ans<<endl; int mx=0; a[0]=0; for(int i=1;i<=n;i++) { //cout<<a[i]<<" "<<a[mx]<<endl; if(a[i]>a[mx]) { mx=i; L.pb(i); vis[i]=1;//cout<<"?"; } } a[0]=(int)(2e18); int mi=0; for(int i=n;i>=1;i--) { if(a[i]<a[mi]) { mi=i; R.pb(i); vis[i]=1; } } reverse(R.begin(),R.end()); //cout<<L.size()<<" "<<R.size()<<'\n'; for(int x=1;x<=n;x++) { if(vis[x]) continue; int l=0,r=L.size()-1,res=-1,xl=-1,xr=-1,yl=-1,yr=-1; while(l<=r) { int mid=(l+r)>>1; if(a[L[mid]]>a[x]) res=mid,r=mid-1; else l=mid+1; } // if(res!=-1) cout<<res<<endl; if(res!=-1) { xl=L[res]; xr=x-1; } l=0; r=R.size()-1; res=-1; while(l<=r) { int mid=(l+r)>>1; if(a[R[mid]]<a[x]) res=mid,l=mid+1; else r=mid-1; } if(res!=-1) { yl=x+1; yr=R[res]; } if(xl!=-1&&yl!=-1) { if(xl>xr||yl>yr) continue; // cout<<xl<<" "<<xr<<" "<<yl<<" "<<yr<<'\n'; p[xl].pb(node(yl,yr,1)); p[xr+1].pb(node(yl,yr,-1)); } } int res=0; for(int i=1;i<=n;i++) { for(node x:p[i]) { // cout<<x.l<<" "<<x.r<<endl; update(1,1,n,x.l,x.r,x.v); } res=max(res,query(1,1,n,1,n)); } cout<<ans-2ll*res<<'\n'; return 0; }

__EOF__

本文作者F x o r G
本文链接https://www.cnblogs.com/xugangfan/p/15872260.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   FxorG  阅读(31)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示