loj

description

给你一个排列\(h_i\),你需要交换任意两个位置上的数使得交换后排列的逆序对数最少。

\(n \le 3\times 10^5\)

sol

首先可以发现,如果交换两个位置\(i,j(h_i>h_j)\),那么逆序对数的减小量就是满足\(i<k<j\)且\(h_j<h_k<h_i\)的\(k\)的数量乘\(2\)。这相当于一个二维数点的问题。

理性分析一下,枚举出来的\(i\)一定是前缀最大值,\(j\)一定是后缀最小值,不然这个矩形内包含的点的数量一定不是最多的。

那么我们就构造出了一个满足前缀最大的集合\(U\)和一个满足后缀最小的集合\(D\),现在要从两个集合中各选出一个构成一个矩形,最大化其中的点数。注意这两个集合中的\(h_i\)都是单调递增的。

我们考虑每一个点\((x,h_x)\)会出现在哪些矩形中。

在\(U\)中二分找到最小的\(l\)满足\(h_l>h_x\),在\(D\)中二分找到最小的\(r\)满足\(h_r<h_x\),那么要使点\((x,h_x)\)被包含在\((i,j)\)构成的矩形内部的条件就是:\(i\in[l,x-1],j\in[x+1,r]\)。

把点转化为矩阵,问题变成求矩形覆盖的最大值,线段树维护扫描线即可。

复杂度\(O(n\log n)\)。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 3e5+5;
int n,h[N],s1[N],t1,s2[N],t2,ins[N],cnt,mx[N<<2],tag[N<<2],c[N],ans;
long long sum;
struct node{
int y,x1,x2,op;
bool operator < (const node &b) const{
if (y==b.y) return op<b.op;
return y<b.y;
}
}p[N<<1];
int binary1(int x){
int l=1,r=t1,res=0;
while (l<=r){
int mid=l+r>>1;
if (h[s1[mid]]>h[x]) res=mid,r=mid-1;
else l=mid+1;
}
return s1[res];
}
int binary2(int x){
int l=1,r=t2,res=0;
while (l<=r){
int mid=l+r>>1;
if (h[s2[mid]]<h[x]) res=mid,r=mid-1;
else l=mid+1;
}
return s2[res];
}
void modify(int x,int l,int r,int ql,int qr,int v){
if (l>=ql&&r<=qr) {mx[x]+=v;tag[x]+=v;return;}
int mid=l+r>>1;
if (ql<=mid) modify(x<<1,l,mid,ql,qr,v);
if (qr>mid) modify(x<<1|1,mid+1,r,ql,qr,v);
mx[x]=max(mx[x<<1],mx[x<<1|1])+tag[x];
}
void mdf(int k){while(k<=n)++c[k],k+=k&-k;}
int qry(int k){int s=0;while(k)s+=c[k],k-=k&-k;return s;}
int main(){
n=gi();
for (int i=1;i<=n;++i) h[i]=gi();
for (int i=1;i<=n;++i) if (i==1||h[i]>h[s1[t1]]) s1[++t1]=i,ins[i]=1;
for (int i=n;i>=1;--i) if (i==n||h[i]<h[s2[t2]]) s2[++t2]=i,ins[i]=1;
for (int i=1;i<=n;++i){
if (ins[i]) continue;
int l=binary1(i),r=binary2(i);
if (l<i&&i<r){
p[++cnt]=(node){i+1,l,i-1,1};
p[++cnt]=(node){r+1,l,i-1,-1};
}
}
sort(p+1,p+cnt+1);
for (int i=1;i<=cnt;++i){
modify(1,1,n,p[i].x1,p[i].x2,p[i].op);
if (p[i].y!=p[i+1].y) ans=max(ans,mx[1]);
}
for (int i=n;i;--i) sum+=qry(h[i]-1),mdf(h[i]);
printf("%lld\n",sum-2*ans);
return 0;
}

[LOJ535]「LibreOJ Round #6」花火的更多相关文章

  1. loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分

    $ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...

  2. 「LibreOJ Round #6」花火

    转化思维的好题! 链接:here 大致题意: 有$ n$个数字,你每次可以交换相邻两个,还有一次交换任意两个元素的机会,求最少的交换次数使得这些数字升序排序(原数列两两不同) $ solotion:$ ...

  3. loj #547. 「LibreOJ β Round #7」匹配字符串

    #547. 「LibreOJ β Round #7」匹配字符串   题目描述 对于一个 01 串(即由字符 0 和 1 组成的字符串)sss,我们称 sss 合法,当且仅当串 sss 的任意一个长度为 ...

  4. [LOJ#531]「LibreOJ β Round #5」游戏

    [LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...

  5. [LOJ#530]「LibreOJ β Round #5」最小倍数

    [LOJ#530]「LibreOJ β Round #5」最小倍数 试题描述 第二天,LCR 终于启动了备份存储器,准备上传数据时,却没有找到熟悉的文件资源,取而代之的是而屏幕上显示的一段话: 您的文 ...

  6. [LOJ#516]「LibreOJ β Round #2」DP 一般看规律

    [LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...

  7. [LOJ#515]「LibreOJ β Round #2」贪心只能过样例

    [LOJ#515]「LibreOJ β Round #2」贪心只能过样例 试题描述 一共有 \(n\) 个数,第 \(i\) 个数 \(x_i\) 可以取 \([a_i , b_i]\) 中任意值. ...

  8. [LOJ#525]「LibreOJ β Round #4」多项式

    [LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...

  9. [LOJ#526]「LibreOJ β Round #4」子集

    [LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...

随机推荐

  1. VS2010/MFC编程入门之十一(对话框:模态对话框及其弹出过程)

    加法计算器对话框程序大家照着做一遍后,相信对基于对话框的程序有些了解了,有个好的开始对于以后的学习大有裨益.趁热打铁,鸡啄米这一节讲讲什么是模态对话框和非模态对话框,以及模态对话框怎样弹出. 一.模态 ...

  2. Python: 复数的数学运算

    写的最新的网络认证方案代码遇到了一个难题,唯一的解决办法就是使用复数空间,需要使用复数来执行一些计算操作. 复数可以用使用函数complex(real, imag) 或者是带有后缀j 的浮点数来指定. ...

  3. Python:导入numpy报错 No module named numpy

    Numpy是python的一种开源的数值计算扩展.这种工具可用来存储和处理大型矩阵,比python自身的嵌套列表结构要高效的多.但是在使用numpy时可能会出错(如上图). 解决办法:下载安装对应版本 ...

  4. Linux Makefile

    动态库: gcc getmaxlen.c –fPIC –shared –o libtest.so ldd -r  libtest.so   静态库: ar crv libfirst.a testlib ...

  5. SQL学习笔记四之MySQL数据操作

    阅读目录 一 介绍 二 插入数据INSERT 三 更新数据UPDATE 四 删除数据DELETE 五 查询数据SELECT 六 权限管理 一 介绍 MySQL数据操作: DML =========== ...

  6. bzoj1999 / P1099 树网的核

    P1099 树网的核 (bzoj数据加强) 前置知识:树的直径 (并不想贴我的智障写法虽然快1倍但内存占用极大甚至在bzoj上MLE) 正常写法之一:用常规方法找到树的直径,在直径上用尺取法找一遍,再 ...

  7. 20145325张梓靖 《Java程序设计》第4周学习总结

    20145325张梓靖 <Java程序设计>第4周学习总结 教材学习内容总结 何谓继承 继承共同行为 继承基本上就是避免多个类间重复定义共同行为:可把相同的程序代码提升为父类:用关键字 e ...

  8. flutter 安装详细教程

    Flutter 是 Google 用以帮助开发者在 iOS 和 Android 两个平台开发高质量原生 UI 的移动 SDK.Flutter 兼容现有的代码,免费且开源,在全球开发者中广泛被使用. 安 ...

  9. Java Spring-IOC和DI

    2017-11-06 16:30:25 IOC:控制反转,将对象的创建权交由Spring管理.IOC底层原理:工厂类+反射+配置文件,创建对象交由工厂类完成. DI(Dependency Inject ...

  10. sshpass使用

    sshpass的使用方法 应用范围:可以在命令行直接使用密码来进行远程连接和远程拉取文件. 使用前提:对于未连接过的主机.而又不输入yes进行确认,需要进行sshd服务的优化: # vim /etc/ ...