[ARC119E] Pancakes (二维偏序,分类讨论)
题面
一个长为
N
N
N 的序列
S
S
S ,最多翻转序列中一个区间,最小化
∑
i
=
2
N
∣
S
i
−
S
i
−
1
∣
\sum_{i=2}^{N}|S_i-S_{i-1}|
i=2∑N∣Si−Si−1∣
并输出这个值。
2
≤
N
≤
3
×
1
0
5
,
1
≤
S
i
≤
1
0
9
2\leq N\leq 3\times10^5,1\leq S_i\leq10^9
2≤N≤3×105,1≤Si≤109
题解
算是非常经典的一道题吧(ZYY金句)
我们发现翻转一个区间
[
l
,
r
]
[l,r]
[l,r] ,两边和中间的相邻数字差都不会变,只有左右端点附近会变,具体地,会令答案加上
∣
S
r
+
1
−
S
l
∣
+
∣
S
r
−
S
l
−
1
∣
−
(
∣
S
r
+
1
−
S
r
∣
+
∣
S
l
−
S
l
−
1
∣
)
|S_{r+1}-S_l|+|S_{r}-S_{l-1}|-(|S_{r+1}-S_{r}|+|S_l-S_{l-1}|)
∣Sr+1−Sl∣+∣Sr−Sl−1∣−(∣Sr+1−Sr∣+∣Sl−Sl−1∣)
这里有四个绝对值,后面两个绝对值分别与
r
r
r 和
l
l
l 单独相关,前面两个就得分类讨论了。
我们不妨令
S
r
+
1
=
x
,
S
r
=
y
,
S
l
=
a
,
S
l
−
1
=
b
S_{r+1}=x,S_r=y\;,\;S_l=a,S_{l-1}=b
Sr+1=x,Sr=y,Sl=a,Sl−1=b,那么前面两个绝对值就是
∣
x
−
a
∣
+
∣
y
−
b
∣
|x-a|+|y-b|
∣x−a∣+∣y−b∣
我们想得到这个减去
∣
x
−
y
∣
+
∣
a
−
b
∣
|x-y|+|a-b|
∣x−y∣+∣a−b∣ 的 最小值。
先鲁莽地讨论讨论(由于是取最值,下面全是可取等的也没问题了):
- x
≥
a
,
y
≥
b
:
(
x
+
y
)
−
(
a
+
b
)
x\geq a,y\geq b:~~~(x+y)-(a+b)
x≥a,y≥b: (x+y)−(a+b)
- x
≥
a
,
y
≤
b
:
(
x
−
y
)
−
(
a
−
b
)
x\geq a,y\leq b:~~~(x-y)-(a-b)
x≥a,y≤b: (x−y)−(a−b)
- x
≤
a
,
y
≥
b
:
(
y
−
x
)
−
(
b
−
a
)
x\leq a,y\geq b:~~~(y-x)-(b-a)
x≤a,y≥b: (y−x)−(b−a)
- x
≤
a
,
y
≤
b
:
−
(
x
+
y
)
+
(
a
+
b
)
x\leq a,y\leq b:~~~-(x+y)+(a+b)
x≤a,y≤b: −(x+y)+(a+b)
然后我们其实没必要区分
(
x
,
y
)
(x,y)
(x,y) 和
(
a
,
b
)
(a,b)
(a,b) 的前后关系,因此其实可以省掉
c
a
s
e
3
、
4
\rm case~3、4
case 3、4 ,只讨论
1
、
2
1、2
1、2 。
分类讨论后,这其实就是个二维偏序。随便用什么数据结构或者直接
C
D
Q
\rm CDQ
CDQ 分治都行。
复杂度
O
(
N
log
N
)
O(N\log N)
O(NlogN) 。
CODE
#include<set>
#include<map>
#include<queue>
#include<ctime>
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAXN 300005
#define ENDL putchar('\n')
#define LL long long
#define DB double
#define lowbit(x) ((-x) & (x))
#define eps 1e-9
LL read() {
LL f = 1,x = 0;char s = getchar();
while(s < '0' || s > '9') {if(s=='-')f = -f;s = getchar();}
while(s >= '0' && s <= '9') {x=x*10+(s-'0');s = getchar();}
return f * x;
}
int n,m,i,j,s,o,k;
int a[MAXN],b[MAXN],a2[MAXN];
int Abs(int x) {return x < 0 ? -x:x;}
map<int,int> mp;
vector<int> bu[MAXN];
LL tre[MAXN<<2],M;
void maketree(int n) {M=1;while(M<n+2)M<<=1;for(int i = 1;i < (M<<1);i ++)tre[i]=1e18;}
void addtree(int x,LL y) {
int s=M+x;tre[s]=min(tre[s],y);s>>=1;
while(s)tre[s]=min(tre[s<<1],tre[s<<1|1]),s>>=1;
}
LL findtree(int l,int r) {
LL as = 1e18; if(l > r) return as;
int s = M+l-1,t = M+r+1;
while(s || t) {
if((s>>1) ^ (t>>1)) {
if(!(s & 1)) as = min(as,tre[s^1]);
if(t & 1) as = min(as,tre[t^1]);
}else break; s >>= 1;t >>= 1;
}return as;
}
int main() {
n = read();
LL sum = 0;
for(int i = 1;i <= n;i ++) {
a[i] = read();
if(i>1) sum += Abs(a[i]-a[i-1]);
b[i] = a[i];
}
sort(b + 1,b + 1 + n);
int nm = 0;
for(int i = 1;i <= n;i ++) {
if(i == 1 || b[i] > b[i-1]) mp[b[i]] = ++ nm;
}
LL asd = 0;
for(int i = 1;i <= n;i ++) {
a2[i] = mp[a[i]];
bu[a2[i]].push_back(i);
if(i < n) asd = min(asd,(LL)-Abs(a[i]-a[i+1])+Abs(a[i]-a[n]));
if(i > 1) asd = min(asd,(LL)-Abs(a[i]-a[i-1])+Abs(a[i]-a[1]));
}
maketree(nm);
for(int i = 1;i <= nm;i ++) {
for(int j = 0;j < (int)bu[i].size();j ++) {
int y = bu[i][j];
if(y > 1) {
LL fd = findtree(1,a2[y-1]) - Abs(a[y]-a[y-1]) + a[y] + a[y-1];
asd = min(asd,fd);
addtree(a2[y-1],(LL)-Abs(a[y]-a[y-1])-(a[y]+a[y-1]));
}
}
}
maketree(nm);
for(int i = 1;i <= nm;i ++) {
for(int j = 0;j < (int)bu[i].size();j ++) {
int y = bu[i][j];
if(y > 1) {
LL fd = findtree(a2[y-1]+1,nm) - Abs(a[y]-a[y-1]) + a[y] - a[y-1];
asd = min(asd,fd);
addtree(a2[y-1],(LL)-Abs(a[y]-a[y-1])-(a[y]-a[y-1]));
}
}
}
printf("%lld\n",sum+asd);
return 0;
}
[ARC119E] Pancakes (二维偏序,分类讨论)的更多相关文章
- [The Preliminary Contest for ICPC Asia Nanjing 2019] A-The beautiful values of the palace(二维偏序+思维)
>传送门< 前言 这题比赛的时候觉得能做,硬是怼了一个半小时,最后还是放弃了.开始想到用二维前缀和,结果$n\leq 10^{6}$时间和空间上都爆了,没有办法.赛后看题解用树状数组,一看 ...
- [luogu4479][BJWC2018]第k大斜率【二维偏序+二分+离散化+树状数组】
传送门 https://www.luogu.org/problemnew/show/P4479 题目描述 在平面直角坐标系上,有 n 个不同的点.任意两个不同的点确定了一条直线.请求出所有斜率存在的直 ...
- 【坐标变换】【二维偏序】【线段树】Gym - 100820G - Racing Gems
题意:第一象限有n个点,你从x正半轴任选一个位置出发,vy恒定,vx可以任意变化,不过只能在-vy/r到vy/r之间变化,问你最多能经过多少个点. 暴力dp是n^2,不可取. 注意到,一个点,所能到达 ...
- cdq分治入门学习 cogs 1752 Mokia nwerc 2015-2016 G 二维偏序
/* CDQ分治的对象是时间. 即对于一个时间段[L, R],我们取mid = (L + R) / 2. 分治的每层只考虑mid之前的修改对mid之后的查询的贡献,然后递归到[L,mid],(mid, ...
- 二维偏序+树状数组【P3431】[POI2005]AUT-The Bus
Description Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到 m编号. 每个路口用两个 ...
- 【贪心】【二维偏序】【权值分块】bzoj1691 [Usaco2007 Dec]挑剔的美食家
既然题目中的要求满足二维偏序,那么我们很自然地想到将所有东西(草和牛)都读进来之后,对一维(美味度)排序,然后在另一维(价值)中取当前最小的. 于是,Splay.mutiset.权值分块什么的都支持查 ...
- 【二维偏序】【树状数组】【权值分块】【分块】poj2352 Stars
经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就 ...
- 树状数组 二维偏序【洛谷P3431】 [POI2005]AUT-The Bus
P3431 [POI2005]AUT-The Bus Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 ...
- 【BZOJ1109】[POI2007]堆积木Klo 二维偏序
[BZOJ1109][POI2007]堆积木Klo Description Mary在她的生日礼物中有一些积木.那些积木都是相同大小的立方体.每个积木上面都有一个数.Mary用他的所有积木垒了一个高塔 ...
随机推荐
- Spring Cloud入门看这一篇就够了
目录 SpringCloud微服务 架构演进 服务调用方式: Euraka服务注册中心 注册中心 服务提供者(服务注册) 服务消费者(服务发现) 服务续约 失效剔除和自我保护 Consul 特性 Co ...
- 内网 Ubuntu 20.04 搭建 docusaurus 项目(或前端项目)的环境(mobaxterm、tigervnc、nfs、node)
内网 Ubuntu 20.04 搭建 docusaurus 项目(或前端项目)的环境 背景 内网开发机是 win7,只能安装 node 14 以下,而 spug 的文档项目采用的是 Facebook ...
- 000 上传本地库到Github远程库过程全记录
20220613 Github上新创建了一个CsImage库,之后本地创建了一个对应名称的目录,并创建本地库,进行了上传操作,记录一下过程 1.Github上CsImage库创建完成 Github上创 ...
- HMS Core 视频编辑服务开放模板能力,助力用户一键Get同款酷炫视频
前言 短视频模板,是快捷创作短视频的一种方式,一般由专业设计师或模板创作人制作,用户只需替换视频模板中的部分素材,便可生成一支与模板一样的创意视频.这种省时省力.无需"烧脑"构思创 ...
- Python if-else的简单表示
常见写法 a = 1 b = 1 c = 2 if a == b: print("true") elif a == c: print("false") else ...
- BUUCTF-数据包中的线索
数据包中的线索 下载看是个流量包,用wireshark打开 有个fenxi.php,里面是个base64编码,尝试解码发现编码不对,那应该就是base64转图片 得到flag
- 你真的会python中的for循环吗
for 循环是 Python 中的通用序列迭代器:它可以单步遍历任何有序序列中的元素.for 语句适用于字符串.列表.元组.其他内置可迭代对象和类创建的新对象. for 通常比 while 循环更容易 ...
- Python教程——常用的os操作详情
Python自动的os库是和操作系统交互的库,常用的操作包括文件/目录操作,路径操作,环境变量操作和执行系统命令等. 文件/目录操作 获取当前目录(pwd): os.getcwd() 切换目录(cd) ...
- Java中时间方法大全01(持续更新)
下面这些方法都可以封装到一个工具类中 /** * 获取当前时间的时间戳 */ public static int getCurrentTimeIntValue() { return (int) (Sy ...
- zenmap安装
发现最新版的KALI不带zenmap了,下面是安装步骤: 安装包转换工具:sudo apt-get install alien fakeroot -y 下载并转换:https://nmap.org/d ...