题目

题目大意

给你一个序列,对于所有\(k\in [1,n]\),求长度为\(k\)的子序列的最大权值,权值为\(a_1-a_2+a_3-...\pm a_k\)


思考历程

这题显然可以背包对吧……

所以就直接背包吧……

比赛的时候我还想到了分治,但由于两边合在一起很慢,所以就直接打暴力了。


正解

题解的线段树做法看得并不是很懂。

所以我就说一个分治的方法。

首先题解有个结论:\(k\)的子序列必然是\(k-2\)的子序列中插入两个数。

记住是插入,而不仅仅是往左右两边扩展。

为什么呢?考虑反证,如果不是这样,就是\(k-2\)的子序列中除去若干个数,然后再插入若干的数。这样实际上相当于从\(k-x\)的状态转移过来,其中\(x>2\)。

所以我们只需要证明从\(k-2\)转移过来比更前面的地方转移过来更优。

假设从\(k-3\)转移过来(其它的情况类似)。

我们将\(k-2\)的序列中按顺序插入\(x\)和\(y\),那么整个序列被分成几个部分\(AxByC\),权值为\(A\pm x-B\pm y+C\)(我们不需要关系\(x\)和\(y\)的正负,\(B\)是原本的贡献,在插入之后符号要翻过来)。

将\(k-3\)的序列中插入\(x\)和\(y\)和\(z\)(我们假设\(x\)和\(y\)插入的位置相同),分成:\(AxByDzE\),权值为\(A \pm x-B \pm y+D \pm z-E\)

比较一下,前半部分抵消了,就变成\(C\)和\(D \pm z-E\)

它们都可以看做一个整体。如果后面的更优,它肯定会在之前替代\(C\)。所以前者是更优一些的。

这就证完了。

然后考虑分治。分治的重点是合并左右两个区间的答案。

考虑由\(s\)转移到\(s+2\)。设转移\(s\)的时候左边用了\(s_1\)个,右边用了\(s_2\)个。

分类讨论看看新插入的两个点放哪边,就有如下三种情况:

  1. 左边\(s_1+2\),右边\(s_2\)。
  2. 左边\(s_1+1\),右边\(s_2+1\)
  3. 左边\(s_1\),右边\(s_2+2\).

根据上面的那个结论,前后两种情况是没有问题的。问题在于第二种情况。

由于是\(+1\),所以就不能用那个结论。

然而,我们发现,在左边\(s1\)或右边\(s2\)的状态中各插一个,其实也算在左边\(s1+1\)或右边\(s2+1\).的状态中。也就是说,\(s1+1\)的状态大于等于\(s1\)插一个转移过去的状态。

所以这样操作没有影响。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <climits>
#define N 100010
int n,a[N];
int _fmn[N],_fmx[N];
int gmn[N],gmx[N];
inline int at(int *a,int x){return x?a[x]:0;}
void dfs(int l,int r){
int *fmn=_fmn+l-1,*fmx=_fmx+l-1;
if (l==r){
fmn[1]=fmx[1]=a[l];
return;
}
int mid=l+r>>1;
dfs(l,mid),dfs(mid+1,r);
int *lmn=_fmn+l-1,*lmx=_fmx+l-1,*rmn=_fmn+mid,*rmx=_fmx+mid,s1=0,s2=0;
for (int i=2;i<=r-l+1;i+=2){
int ts1,ts2,v=INT_MIN;
if (s2+2<=r-mid){
int tmp=(s1&1?at(lmx,s1)-at(rmn,s2+2):at(lmx,s1)+at(rmx,s2+2));
if (tmp>v)
v=tmp,ts1=s1,ts2=s2+2;
}
if (s1+1<=mid-l+1 && s2+1<=r-mid){
int tmp=(s1+1&1?at(lmx,s1+1)-at(rmn,s2+1):at(lmx,s1+1)+at(rmx,s2+1));
if (tmp>v)
v=tmp,ts1=s1+1,ts2=s2+1;
}
if (s1+2<=mid-l+1){
int tmp=(s1+2&1?at(lmx,s1+2)-at(rmn,s2):at(lmx,s1+2)+at(rmx,s2));
if (tmp>v)
v=tmp,ts1=s1+2,ts2=s2;
}
gmx[i]=v;
s1=ts1,s2=ts2;
}
s1=0,s2=0;
for (int i=2;i<=r-l+1;i+=2){
int ts1,ts2,v=INT_MAX;
if (s2+2<=r-mid){
int tmp=(s1&1?at(lmn,s1)-at(rmx,s2+2):at(lmn,s1)+at(rmn,s2+2));
if (tmp<v)
v=tmp,ts1=s1,ts2=s2+2;
}
if (s1+1<=mid-l+1 && s2+1<=r-mid){
int tmp=(s1+1&1?at(lmn,s1+1)-at(rmx,s2+1):at(lmn,s1+1)+at(rmn,s2+1));
if (tmp<v)
v=tmp,ts1=s1+1,ts2=s2+1;
}
if (s1+2<=mid-l+1){
int tmp=(s1+2&1?at(lmn,s1+2)-at(rmx,s2):at(lmn,s1+2)+at(rmn,s2));
if (tmp<v)
v=tmp,ts1=s1+2,ts2=s2;
}
gmn[i]=v;
s1=ts1,s2=ts2;
}
if (lmx[1]>rmx[1])
s1=1,s2=0,gmx[1]=lmx[1];
else
s1=0,s2=1,gmx[1]=rmx[1];
for (int i=3;i<=r-l+1;i+=2){
int ts1,ts2,v=INT_MIN;
if (s2+2<=r-mid){
int tmp=(s1&1?at(lmx,s1)-at(rmn,s2+2):at(lmx,s1)+at(rmx,s2+2));
if (tmp>v)
v=tmp,ts1=s1,ts2=s2+2;
}
if (s1+1<=mid-l+1 && s2+1<=r-mid){
int tmp=(s1+1&1?at(lmx,s1+1)-at(rmn,s2+1):at(lmx,s1+1)+at(rmx,s2+1));
if (tmp>v)
v=tmp,ts1=s1+1,ts2=s2+1;
}
if (s1+2<=mid-l+1){
int tmp=(s1+2&1?at(lmx,s1+2)-at(rmn,s2):at(lmx,s1+2)+at(rmx,s2));
if (tmp>v)
v=tmp,ts1=s1+2,ts2=s2;
}
gmx[i]=v;
s1=ts1,s2=ts2;
}
if (lmn[1]<rmn[1])
s1=1,s2=0,gmn[1]=lmn[1];
else
s1=0,s2=1,gmn[1]=rmn[1];
for (int i=3;i<=r-l+1;i+=2){
int ts1,ts2,v=INT_MAX;
if (s2+2<=r-mid){
int tmp=(s1&1?at(lmn,s1)-at(rmx,s2+2):at(lmn,s1)+at(rmn,s2+2));
if (tmp<v)
v=tmp,ts1=s1,ts2=s2+2;
}
if (s1+1<=mid-l+1 && s2+1<=r-mid){
int tmp=(s1+1&1?at(lmn,s1+1)-at(rmx,s2+1):at(lmn,s1+1)+at(rmn,s2+1));
if (tmp<v)
v=tmp,ts1=s1+1,ts2=s2+1;
}
if (s1+2<=mid-l+1){
int tmp=(s1+2&1?at(lmn,s1+2)-at(rmx,s2):at(lmn,s1+2)+at(rmn,s2));
if (tmp<v)
v=tmp,ts1=s1+2,ts2=s2;
}
gmn[i]=v;
s1=ts1,s2=ts2;
}
for (int i=1;i<=r-l+1;++i)
fmn[i]=gmn[i],fmx[i]=gmx[i];
}
int main(){
freopen("pe.in","r",stdin);
freopen("pe.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&a[i]);
dfs(1,n);
for (int i=1;i<=n;++i)
printf("%d ",_fmx[i]);
return 0;
}

总结

结论是要靠猜的……

[JZOJ6355] 【NOIP2019模拟】普 24/100的更多相关文章

  1. 2017冬季24集训模拟题-24星球的末日(Floyd)

    24 星球的末日[问题描述]24 星球的世界末日就要到了 , 可是诺亚方舟还没有制造完成 . 为了制造诺亚方舟这个星球上的所有国家都站在统一战线 . 现在一共有n个国家 , 一个国家到另一个国家都有一 ...

  2. test20190815 NOIP2019 模拟题

    100+60+40=200,被后面两个题卡着我很不爽. 立方数 [问题描述] 作为 XX 战队的狂热粉丝,MdZzZZ 看到了自己心仪的队伍在半决赛落败,顿时 心灰意冷.看着自己手中的从黄牛那里抢来的 ...

  3. test20190814 NOIP2019 模拟题

    二叉树 [问题描述] 从前有一棵二叉树,我们用如下方式来表示这棵二叉树. 如果一个节点没有儿子,我们用"0"来表示他. 如果一个节点有一个儿子,我们对它的表示以"1&qu ...

  4. linux下模拟CPU占用100%小程序

    在做一个测试时,需要模拟服务器CPU占用满的情况,在查阅相关资料后,发现网上程序不太好用, 原文在这:http://www.2cto.com/os/201304/202068.html 优化后如下: ...

  5. [考试反思]0817NOIP模拟测试24:冲淡

    一切都还好吗? 是啊,还好. 前两名仍然被外校包揽/ B哥140撑住场面,120/110/100不等.我90分混吃等死排了个大并列第10. 考前说要考凸包,打开了几个博客慢慢看一直到考试开始. 然而我 ...

  6. test20190827 NOIP2019 模拟赛

    100+100+50=250.最后那道期望题需要用另外的方式统计. 精灵加护 ljss 被 M 个敌人打倒在地上啦!每个敌人有一个威力值 bi.但是他手中还拥有 N 把武器!每把武器有一个威力值 ai ...

  7. test20190826 NOIP2019 模拟赛

    100+100+40=240.我觉得如果没做过第三题考场上却能想出来的都是神仙. 基因突变 [问题描述] 邪恶的 707 刚刚从白垩纪穿越回来,心中产生了一个念头:我要统治人类! 但是统治人类是很庞大 ...

  8. test20190818 NOIP2019 模拟赛

    0+0+20=20,不给大样例,小数据又水,还没有题解的垃圾题. A 题 问题描述: long long ago, Lxhgww 统治的国家里有 n 个城市,其中某一个城市是 capital (首都) ...

  9. test20190816 NOIP2019 模拟赛

    100+100+20=220,T3吐槽:整个考室没有一个人正确地理解了题意. 树上路径(phantasm) Akari 的学校的校门前生长着一排 n 棵树,从西向东依次编号为 1 ∼ n.相邻两棵树间 ...

随机推荐

  1. 基于React Native的跨三端应用架构实践

    作者|陈子涵 编辑|覃云 “一次编写, 到处运行”(Write once, run anywhere ) 是很多前端团队孜孜以求的目标.实现这个目标,不但能以最快的速度,将应用推广到各个渠道,而且还能 ...

  2. 08-03-re-模块

    一组特殊符号组成的表达式,用于描述某种规则.该应用场景生活中随处可见. ​ 例如:让有志青年过上体面的生活,这里面就由规则,即有志青年. 正则表达式的作用,以及使用场景 ​ 1.用于从字符串中匹配满足 ...

  3. Vue学习笔记【23】——Vue组件(组件的定义)

    定义Vue组件 什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可: 组件化和模块化的不同: ...

  4. jQuery, js 验证两次输了密码的一相同

    <div class="form-group"> <label class="col-sm-2 control-label font"> ...

  5. Ruby——输入&输出

    Ruby的输入和输出操作.输入是程序从键盘.文件或者其他程序读取数据.输出是程序产生数据.可以输出到屏幕.文件或者其他程序. Ruby中的一些类有些方法会执行输入&输出操作.例如Kernel. ...

  6. posix_rpi_common.cmake学习

    # This file is shared between posix_rpi_native.cmake 这个文件在posix_rpi_native.cmake和posix_rpi_cross.cma ...

  7. Ext 选项卡面板TabPanel

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. shellcode加密与解密

    // Encoder.cpp : Defines the entry point for the console application.// #include "stdafx.h" ...

  9. php开发面试题---php面向对象详解(对象的主要三个特性)

    php开发面试题---php面向对象详解(对象的主要三个特性) 一.总结 一句话总结: 对象的行为:可以对 对象施加那些操作,开灯,关灯就是行为. 对象的形态:当施加那些方法是对象如何响应,颜色,尺寸 ...

  10. MAC OpenGL 环境搭建

    MAC OpenGL 环境搭建 基础库介绍 先要安装两个库一个是GLEW(OpenGL Extension Wrangler Library),另外一个是GLFW(Graphics Library F ...