SS241007B. 逆序对(inverse)

news/2024/10/7 21:21:51/文章来源:https://www.cnblogs.com/liyixin0514/p/18450491

SS241007B. 逆序对(inverse)

题意

给你一个长度为 \(n\) 的排列,你可以选择一对 \((i,j)\),交换 \(p_i,p_j\),或者不操作,使减少的逆序对个数最多,求最多减少几个逆序对。

思路

首先考虑交换 \(i,j\) 会对哪些部分的逆序对数量产生影响。不难发现,如果我们画一个二维平面,上面有 \(n\) 个点 \((i,p_i)\),那么交换 \((p_i,p_j)\) 减少的逆序对个数就是:设以 \((i,p_i)\) 为左上角,以 \((j,p_j)\) 为右下角的矩形内部覆盖了 \(s\) 个点,减少的逆序对个数就是 \(2s+1\)

因此问题转化为对所有 \((i,j)\),求矩形内部覆盖的点数最多。

枚举所有左上角和右上角,然后二维前缀和计算矩形内部点数,时间复杂度是 \(O(n^2)\) 的。

通过敏锐的观察,可以发现不是所有点都有可能成为矩形的左上角或者右下角的。设点 \((k,p_k)\) 在点 \((i,p_i)\) 的右下方,那么左上角一定不会选择 \(k\),因为选择 \(i\) 必然更优,因此只有等于前缀最大值的 \(p_i\) 可能成为矩形左上角。同理可得,只有后缀最小值可能成为矩形右下角。长成图像就是所有可能的左上角,所有可能的右上角,都是单调递增的。

那么对于部分分的随机数据,发现随机条件下可能的左上角及右上角基本上都不超过 \(100\),因此直接枚举左上角、右上角,然后树状数组求一下矩形内部的点,就可以获得 \(70\) 分的高分了。

其实容易发现有一个很有前途的决策单调性,对于向右移动的矩形左上角,决策点(右下角)一定单调向右移动。因为左上端点向右上移动,所有决策(选择每个右下端点的矩形内点数)的变化量一定是越右边的越大。因此一个左边的决策点如果没有一个右边的决策点优,之后它会更加不优,可以直接扔掉它了。因此对于单调右上的左上角,决策点也是单调右上的。

但是题解的做法并没有利用这个决策单调性,场上我也没有想到很好地利用它的方法。

我们考虑转换思路,枚举每个点,处理这个点对哪些矩形有贡献。

发现这个点一定是对左上端点在这个点的左上方,右下端点在这个点的右下方,的矩形有贡献,也就是连续的一段左端点匹配连续的一段右端点。

一个十分巧妙的转化是,创建一个二维平面 \((左上端点编号,右下端点编号)\),叫做平面 2,刚刚那个二维平面叫做平面 1。然后每个平面 1 的点就相当于把平面 2 的一个矩形加 \(1\),最后问平面 2 最大的点的权值是多少。

由于我们不能把平面 2 建出来,所以我们离线所有对平面 2 的操作,然后扫描线,用线段树维护最大值即可。时间复杂度是 \(O(n \log n)\) 的。

code

#include<bits/stdc++.h>
// #define LOCAL
#define sf scanf
#define pf printf
#define rep(x,y,z) for(int x=y;x<=z;x++)
#define per(x,y,z) for(int x=y;x>=z;x--)
using namespace std;
typedef long long ll;
const int N=1e6+7;
namespace io {const int SIZE = (1 << 25) + 1;char ibuf[SIZE], *iS, *iT;char obuf[SIZE], *oS = obuf, *oT = oS + SIZE - 1, c, qu[64];int f, qr;#define gc() (iS == iT ? (iT = (iS = ibuf) + fread (ibuf, 1, SIZE, stdin), (iS == iT ? EOF : *iS ++)) : *iS ++)inline void flush () {fwrite (obuf, 1, oS - obuf, stdout);oS = obuf;}inline void putc (char x) {*oS ++ = x;if (oS == oT) flush ();}template <class I> inline void read (I &x) {for (f = 1, c = gc(); c < '0' || c > '9'; c = gc()) if (c == '-') f = -1;for (x = 0; c <= '9' && c >= '0'; c = gc()) x = x * 10 + (c & 15); x = f == -1 ? -x : x;}template <class I> inline void print (I x) {if (! x) putc ('0'); if (x < 0) putc ('-'), x = -x;while (x) qu[ ++ qr] = x % 10 + '0',  x /= 10;while (qr) putc (qu[qr -- ]);}struct Flusher_ {~Flusher_(){flush();}}io_flusher_;
}
using io :: read;
using io :: putc;
using io :: print;
int n,p[N];
int lvec[N],rvec[N],ls[N],rs[N];
int cntl,cntr;
typedef pair<int,int> pii;
typedef vector<pii > vpii;
#define fi first 
#define se second
vpii opt[N];
int mx[N<<2],tag[N<<2];
int ans=0;
inline void maketag(int u,int val) {tag[u]+=val;mx[u]+=val;
}
inline void pushdown(int u) {if(tag[u]) maketag(u<<1,tag[u]),maketag(u<<1|1,tag[u]),tag[u]=0;}
inline void pushup(int u) {mx[u]=max(mx[u<<1],mx[u<<1|1]);}
void update(int u,int l,int r,int x,int val) {if(l>=x) {maketag(u,val);return;}pushdown(u);int mid=(l+r)>>1;if(x<=mid) update(u<<1,l,mid,x,val);update(u<<1|1,mid+1,r,x,val);pushup(u);
}
bool check() {rep(i,2,n) if(p[i]<p[i-1]) return 0;return 1;
}
int main(){#ifdef LOCALfreopen("in.txt","r",stdin);freopen("my.out","w",stdout);#elsefreopen("inverse.in","r",stdin);freopen("inverse.out","w",stdout);#endifread(n);rep(i,1,n) read(p[i]);if(check()) {print(0);return 0;}int tmp=0;rep(i,1,n) {tmp=max(tmp,p[i]);if(p[i]==tmp) lvec[++cntl]=i,ls[cntl]=p[i];}tmp=N;per(i,n,1) {tmp=min(tmp,p[i]);if(p[i]==tmp) rvec[++cntr]=i,rs[cntr]=p[i];}reverse(rvec+1,rvec+cntr+1);reverse(rs+1,rs+cntr+1);// pf("%d %d\n",cntl,cntr);// rep(i,1,cntl) pf("%d ",lvec[i]);pf("\n");// rep(i,1,cntr) pf("%d ",rvec[i]);pf("\n");int idl=1,idr=rvec[1]==1?1:0;// pf("\n");rep(i,2,n-1) {if(i==lvec[idl+1]) idl++;if(i==rvec[idr+1]) idr++;int l=upper_bound(ls+1,ls+idl+1,p[i])-ls,r=lower_bound(rs+idr,rs+cntr+1,p[i])-rs-1;// pf("%d %d %d %d\n",l,idl,idr,r);if(idr+1>r) continue;opt[idr+1].push_back({l,1}),opt[idr+1].push_back({idl+1,-1});opt[r+1].push_back({l,-1}),opt[r+1].push_back({idl+1,1});}rep(i,1,cntr) {for(pii op:opt[i]) {// pf("%d %d %d\n",i,op.fi,op.se);if(op.fi>=1&&op.fi<=cntl)update(1,1,cntl,op.fi,op.se);}ans=max(ans,mx[1]);}print(ans*2+1);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/809615.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IDEA如何快速定位到当前打开文件所在的目录

前言 我们在使用IDEA开发时,经常需要知道当前打开的文件是在哪个目录,这个可以在上方看到具体的目录。 但是,当我们需要知道这个目录下有哪些文件或者想要复制当前文件的时候,就需要快速定位当前文件的目录了。 那么,我们应该如何操作呢? 如何操作定位当前打开文件目录 首…

Vulnhub 靶机 THE PLANETS: EARTH

0x01信息收集 1.1、nmap扫描 IP段扫描,确定靶机地址 平扫描 nmap 192.168.1.0/24扫描结果(部分) Nmap scan report for earth.local (192.168.1.129) Host is up (0.0015s latency). Not shown: 983 filtered tcp ports (no-response), 14 filtered tcp ports (admin-prohib…

基于 Prometheus+Grafana+Alertmanager 搭建 K8S 云监控告警平台(附配置告警至QQ、钉钉)

目录一、机器规划二、部署安装 node-exporter、prometheus、Grafana、kube-state-metrics1、创建 monitor-sa 命名空间2、安装node-exporter组件2.1、说明2.2、应用资源清单2.3、通过node-exporter采集数据3、k8s 集群中部署 prometheus3.1、创建一个 sa 账号3.2、将 sa 账号 m…

2024.10.7 鲜花

【UNR #3】百鸽笼【UNR #3】百鸽笼花の塔 君が持ってきた漫画 くれた知らない名前のお花 今日はまだ来ないかな? 初めての感情知ってしまった 窓に飾った絵画をなぞってひとりで宇宙を旅して それだけでいいはずだったのに 君の手を握ってしまったら 孤独を知らないこの街には…

基于 Prometheus+Grafana+Alertmanager 搭建 K8S 云平台系统(附配置告警至QQ、钉钉)

目录一、机器规划二、部署安装 node-exporter、prometheus、Grafana、kube-state-metrics1、创建 monitor-sa 命名空间2、安装node-exporter组件2.1、说明2.2、应用资源清单2.3、通过node-exporter采集数据3、k8s 集群中部署 prometheus3.1、创建一个 sa 账号3.2、将 sa 账号 m…

软件工程第二次结对作业

软件工程 https://edu.cnblogs.com/campus/fzu/SE2024作业要求 https://edu.cnblogs.com/campus/fzu/SE2024/homework/13281作业目标 基于第一次结对作业项目程序的实现学号 102201127合作伙伴 102201129项目分工: 102201129周鑫: 前端开发: 设计和实现用户界面。 确保界面响…

20241007

sequence 我们会发现,我们每次删的一定是长度最短的那个,所以我们可以最开始按照长的排一下序,然后用线段树维护每一个区间中还有几个数,每次加上答案后在两个端点打上标记即可 #include <bits/stdc++.h> #define _1 (__int128)1using namespace std; using ll = long lo…

软件工程week2课程作业|“物品复活“软件开发

“物品复活”软件开发 作业要求 大学生经常有些物品觉得扔掉可惜,不处理又觉得浪费自己的地方。请你编写一个物品“复活”软件 该程序允许添加物品的信息(物品名称,物品描述,联系人信息),删除物品的信息,显示物品列表,也允许查找物品的信息 你实现的程序可以采用命令行…

[42] (多校联训) A层冲刺NOIP2024模拟赛03

今天的乐子今天的乐子2 昨天晚上做梦 梦见自己被关进戒网瘾学校 里面的老师全和疯子一样 然后我和这帮疯子老师比疯 疯子老师发现他们没我疯 所以就把我放了今天的乐子3 lhx 罗曼蒂克的辟谷A.五彩斑斓 赛时的想法 \(n^4\) 的做法,设 \(f_{i,j,k,l}\) 表示以 \((i,j)\) 为左上角…

Metasploit渗透测试框架学习(一)基本使用教程

1.Metasploit框架结构 1.1总览基础库文件Rex为最底层,实现网络套接字、网络应用协议、客户端服务端交互、数据库支持等 framework-core实现与上层模块交互的接口 framework-base对framework-core的扩展封装,用于提供各种接口供用户调用基于framework-base实现的六大模块Explo…

统计学(十三)——相关分析

img { display: block; margin-left: auto; margin-right: auto } table { margin-left: auto; margin-right: auto } 相关分析是用于研究多个变量之间相互关系的统计方法,最早由英国统计学家卡尔皮尔逊(Karl Pearson)于1896年提出。皮尔逊通过对变量间线性关系的深入研究,…

前端模块化进化史:从全局 function 到 ES Modules

目前,前端开发已经离不开由 CommonJS、ES Modules 和 Webpack 构建的模块化开发环境。无论是 JavaScript、CSS、图片还是其他资源,都可以作为一个模块来处理。那么,模块化究竟是如何发展到今天的呢? 全局函数模式 最初的前端模块化尝试是通过 全局函数来实现的。例如,在一…