题面

一个长为

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∣ 的 最小值。

先鲁莽地讨论讨论(由于是取最值,下面全是可取等的也没问题了):

  1. 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)

  2. 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)

  3. 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)

  4. 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 (二维偏序,分类讨论)的更多相关文章

  1. [The Preliminary Contest for ICPC Asia Nanjing 2019] A-The beautiful values of the palace(二维偏序+思维)

    >传送门< 前言 这题比赛的时候觉得能做,硬是怼了一个半小时,最后还是放弃了.开始想到用二维前缀和,结果$n\leq 10^{6}$时间和空间上都爆了,没有办法.赛后看题解用树状数组,一看 ...

  2. [luogu4479][BJWC2018]第k大斜率【二维偏序+二分+离散化+树状数组】

    传送门 https://www.luogu.org/problemnew/show/P4479 题目描述 在平面直角坐标系上,有 n 个不同的点.任意两个不同的点确定了一条直线.请求出所有斜率存在的直 ...

  3. 【坐标变换】【二维偏序】【线段树】Gym - 100820G - Racing Gems

    题意:第一象限有n个点,你从x正半轴任选一个位置出发,vy恒定,vx可以任意变化,不过只能在-vy/r到vy/r之间变化,问你最多能经过多少个点. 暴力dp是n^2,不可取. 注意到,一个点,所能到达 ...

  4. cdq分治入门学习 cogs 1752 Mokia nwerc 2015-2016 G 二维偏序

    /* CDQ分治的对象是时间. 即对于一个时间段[L, R],我们取mid = (L + R) / 2. 分治的每层只考虑mid之前的修改对mid之后的查询的贡献,然后递归到[L,mid],(mid, ...

  5. 二维偏序+树状数组【P3431】[POI2005]AUT-The Bus

    Description Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 到 m编号. 每个路口用两个 ...

  6. 【贪心】【二维偏序】【权值分块】bzoj1691 [Usaco2007 Dec]挑剔的美食家

    既然题目中的要求满足二维偏序,那么我们很自然地想到将所有东西(草和牛)都读进来之后,对一维(美味度)排序,然后在另一维(价值)中取当前最小的. 于是,Splay.mutiset.权值分块什么的都支持查 ...

  7. 【二维偏序】【树状数组】【权值分块】【分块】poj2352 Stars

    经典问题:二维偏序.给定平面中的n个点,求每个点左下方的点的个数. 因为 所有点已经以y为第一关键字,x为第二关键字排好序,所以我们按读入顺序处理,仅仅需要计算x坐标小于<=某个点的点有多少个就 ...

  8. 树状数组 二维偏序【洛谷P3431】 [POI2005]AUT-The Bus

    P3431 [POI2005]AUT-The Bus Byte City 的街道形成了一个标准的棋盘网络 – 他们要么是北南走向要么就是西东走向. 北南走向的路口从 1 到 n编号, 西东走向的路从1 ...

  9. 【BZOJ1109】[POI2007]堆积木Klo 二维偏序

    [BZOJ1109][POI2007]堆积木Klo Description Mary在她的生日礼物中有一些积木.那些积木都是相同大小的立方体.每个积木上面都有一个数.Mary用他的所有积木垒了一个高塔 ...

随机推荐

  1. Spring Cloud入门看这一篇就够了

    目录 SpringCloud微服务 架构演进 服务调用方式: Euraka服务注册中心 注册中心 服务提供者(服务注册) 服务消费者(服务发现) 服务续约 失效剔除和自我保护 Consul 特性 Co ...

  2. 内网 Ubuntu 20.04 搭建 docusaurus 项目(或前端项目)的环境(mobaxterm、tigervnc、nfs、node)

    内网 Ubuntu 20.04 搭建 docusaurus 项目(或前端项目)的环境 背景 内网开发机是 win7,只能安装 node 14 以下,而 spug 的文档项目采用的是 Facebook ...

  3. 000 上传本地库到Github远程库过程全记录

    20220613 Github上新创建了一个CsImage库,之后本地创建了一个对应名称的目录,并创建本地库,进行了上传操作,记录一下过程 1.Github上CsImage库创建完成 Github上创 ...

  4. HMS Core 视频编辑服务开放模板能力,助力用户一键Get同款酷炫视频

    前言 短视频模板,是快捷创作短视频的一种方式,一般由专业设计师或模板创作人制作,用户只需替换视频模板中的部分素材,便可生成一支与模板一样的创意视频.这种省时省力.无需"烧脑"构思创 ...

  5. Python if-else的简单表示

    常见写法 a = 1 b = 1 c = 2 if a == b: print("true") elif a == c: print("false") else ...

  6. BUUCTF-数据包中的线索

    数据包中的线索 下载看是个流量包,用wireshark打开 有个fenxi.php,里面是个base64编码,尝试解码发现编码不对,那应该就是base64转图片 得到flag

  7. 你真的会python中的for循环吗

    for 循环是 Python 中的通用序列迭代器:它可以单步遍历任何有序序列中的元素.for 语句适用于字符串.列表.元组.其他内置可迭代对象和类创建的新对象. for 通常比 while 循环更容易 ...

  8. Python教程——常用的os操作详情

    Python自动的os库是和操作系统交互的库,常用的操作包括文件/目录操作,路径操作,环境变量操作和执行系统命令等. 文件/目录操作 获取当前目录(pwd): os.getcwd() 切换目录(cd) ...

  9. Java中时间方法大全01(持续更新)

    下面这些方法都可以封装到一个工具类中 /** * 获取当前时间的时间戳 */ public static int getCurrentTimeIntValue() { return (int) (Sy ...

  10. zenmap安装

    发现最新版的KALI不带zenmap了,下面是安装步骤: 安装包转换工具:sudo apt-get install alien fakeroot -y 下载并转换:https://nmap.org/d ...