【Loj#535】花火(线段树,扫描线)
【Loj#535】花火(线段树,扫描线)
题面
题解
首先如果不考虑交换任意两个数这个操作,答案就是逆序对的个数。
那么暴力就是枚举交换哪个两个数,然后用数据结构之类的东西动态维护逆序对。
但是这样还不够。
仔细观察哪些点交换了才有意义。
假设交换的位置是\(l,r\)
首先必须有\(h[l]\gt h[r]\),这个很显然,如果把一个更大的数换到了前面显然不优。
其次,\(l\)必须是前缀的最大值。
如果\(l\)不是前缀最大值,那么存在一个位置\(i\)满足\(h[i]\gt h[l]\gt h[r]\)
那么直接交换\(i,r\)显然更优。
同理,\(r\)必须是后缀的最小值。
那么,首先把所有的前缀最大值和后缀最小值预处理出来。
每次交换的时候,我们发现减少的逆序对数量就是
\(l<i<r,h[l]>h[i]>h[r]\)的所有\(i\)的个数。
发现这就是一个二维数点,用扫描线解决即可。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 333333
#define lson (now<<1)
#define rson (now<<1|1)
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
ll ans,now;
int n,a[MAX],cnt;
int st1[MAX],st2[MAX],top1,top2;
bool ins[MAX];
struct Node{int y,l,r,opt;}p[MAX<<1];
bool operator<(Node a,Node b)
{
if(a.y!=b.y)return a.y<b.y;
return a.opt<b.opt;
}
int binary1(int x)
{
int l=1,r=top1,ret=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(a[st1[mid]]>a[x])ret=mid,r=mid-1;
else l=mid+1;
}
return st1[ret];
}
int binary2(int x)
{
int l=1,r=top2,ret=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(a[st2[mid]]<a[x])ret=mid,r=mid-1;
else l=mid+1;
}
return st2[ret];
}
struct SegNode{int mx,tag;}t[MAX<<2];
void Modify(int now,int l,int r,int L,int R,int w)
{
if(L<=l&&r<=R){t[now].mx+=w;t[now].tag+=w;return;}
int mid=(l+r)>>1;
if(L<=mid)Modify(lson,l,mid,L,R,w);
if(R>mid)Modify(rson,mid+1,r,L,R,w);
t[now].mx=max(t[lson].mx,t[rson].mx)+t[now].tag;
}
int c[MAX];
int lb(int x){return x&(-x);}
void add(int x){while(x<=n)++c[x],x+=lb(x);}
int getsum(int x){int ret=0;while(x)ret+=c[x],x-=lb(x);return ret;}
int main()
{
//freopen("hanabi.in","r",stdin);
//freopen("hanabi.out","w",stdout);
n=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<=n;++i)if(i==1||a[i]>a[st1[top1]])st1[++top1]=i,ins[i]=true;
for(int i=n;i>=1;--i)if(i==n||a[i]<a[st2[top2]])st2[++top2]=i,ins[i]=true;
for(int i=1;i<=n;++i)
if(!ins[i])
{
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].l,p[i].r,p[i].opt);
if(p[i].y!=p[i+1].y)ans=max(ans,1ll*t[1].mx);
}
ans<<=1;ans*=-1;
for(int i=1;i<=n;++i)add(a[i]),ans+=i-getsum(a[i]);
printf("%lld\n",ans);
return 0;
}
【Loj#535】花火(线段树,扫描线)的更多相关文章
- 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)
D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- Codeforces VK CUP 2015 D. Closest Equals(线段树+扫描线)
题目链接:http://codeforces.com/contest/522/problem/D 题目大意: 给你一个长度为n的序列,然后有m次查询,每次查询输入一个区间[li,lj],对于每一个查 ...
- 【POJ-2482】Stars in your window 线段树 + 扫描线
Stars in Your Window Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11706 Accepted: ...
- HDU 4419 Colourful Rectangle --离散化+线段树扫描线
题意: 有三种颜色的矩形n个,不同颜色的矩形重叠会生成不同的颜色,总共有R,G,B,RG,RB,GB,RGB 7种颜色,问7种颜色每种颜色的面积. 解法: 很容易想到线段树扫描线求矩形面积并,但是如何 ...
- BZOJ-3228 棋盘控制 线段树+扫描线+鬼畜毒瘤
3228: [Sdoi2008]棋盘控制 Time Limit: 10 Sec Memory Limit: 128 MB Submit: 23 Solved: 9 [Submit][Status][D ...
- BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞
看数据范围像是个暴力,而且理论复杂度似乎可行,然后被卡了两个点...然后来了个乱搞的线段树+扫描线.. 3225: [Sdoi2008]立方体覆盖 Time Limit: 2 Sec Memory L ...
- hdu 5091(线段树+扫描线)
上海邀请赛的一道题目,看比赛时很多队伍水过去了,当时还想了好久却没有发现这题有什么水题的性质,原来是道成题. 最近学习了下线段树扫描线才发现确实是挺水的一道题. hdu5091 #include &l ...
- POJ1151+线段树+扫描线
/* 线段树+扫描线+离散化 求多个矩形的面积 */ #include<stdio.h> #include<string.h> #include<stdlib.h> ...
- POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]
题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...
- HDU 5107 线段树扫描线
给出N个点(x,y).每一个点有一个高度h 给出M次询问.问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对全部的点和询 ...
随机推荐
- 九、Django之ORM
一.ORM概述 用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作. 到目前为止,当我们的程序涉及到数据库相关操作时,一般操作流 ...
- 180723-Quick-Task 动态脚本支持框架之结构设计篇
文章链接:https://liuyueyi.github.io/hexblog/2018/07/23/180723-Quick-Task-动态脚本支持框架之结构设计篇/ Quick-Task 动态脚本 ...
- selenium自动化之定位多个元素
前面我们讲的都是如何定位单个元素,下面讲下怎么去定位多个元素,并且输出文本. 以百度为例:获取标红的这一组元素的文本 这里我用到的是xpath来定位的://div[@id="u1" ...
- 使用PHP写ajax接口
使用PHP写ajax接口 之前有学过php都是前后端没有分离的,所以也想去了解后端是怎么写出ajax接口的,可能问了别人或者上网找了很多资料都很有有点懵,或者说直接用TP或者lavarel这些后端框架 ...
- TW实习日记:第六天
今日的一整天都是在开发微信相关的接口,因为项目的系统是嵌在企业微信中,所以不可避免的要产生微信UserID和企业系统ID的匹配关系,那么就需要用手机号或是邮箱这种两边都存在的唯一参数进行匹配.然后再将 ...
- linux中匹配正确的ip地址
1.假设IP地址是规范的,没有出错误的 sed -n "/[0-9]\{1,3\}.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}/p" test ...
- 算法与AI的暗黑面:3星|《算法的陷阱:超级平台、算法垄断与场景欺骗》
算法的陷阱:超级平台.算法垄断与场景欺骗 全书讲算法与AI的暗黑面:价格歧视.导致算法军备竞赛.导致商家降价冲动降低.平台作恶(向劣质商家收费导致品质下降.与开发商一起分析用户隐私)等. 作者从商业. ...
- Python中如何实现im2col和col2im函数(sliding类型)
今天来说说im2col和col2im函数,这是MATLAB中两个内置函数,经常用于数字图像处理中.其中im2col函数在<MATLAB中的im2col函数>一文中已经进行了简单的介绍. 一 ...
- 高可用Kubernetes集群-12. 部署kubernetes-ingress
参考文档: Github:https://github.com/kubernetes/ingress-nginx Kubernetes ingress:https://kubernetes.io/do ...
- [CF1137]Museums Tour
link \(\text{Description:}\) 一个国家有 \(n\) 个城市,\(m\) 条有向道路组成.在这个国家一个星期有 \(d\) 天,每个城市有一个博物馆. 有个旅行团在城市 \ ...