题目

题目大意

给你一个序列,对于所有\(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. Rikka with Competition

    Rikka with Competition 给出一个大小为n的集合\(\{a_i\}\),每次从集合中随机挑出一对数\(a_i,a_j\),如果\(|a_i-a_j|>K\),那么从集合中删掉 ...

  2. python 文件复制压缩

    import os import time #这里是需要文件所在的位置 source=['"C:\\My Documents"',"C:\\Code"] #转换 ...

  3. 决策树(Decision Tree)算法 python简单实现

    "" """ import numpy as np from math import log import operator import json ...

  4. 6383. 【NOIP2019模拟2019.10.07】果实摘取

    题目 题目大意 给你一个由整点组成的矩形,坐标绝对值范围小于等于\(n\),你在\((0,0)\),一开始面向\((1,0)\),每次转到后面第\(k\)个你能看到的点,然后将这条线上的点全部标记删除 ...

  5. javascript null vs undefined

    这个是很古老的问题了. 一直存在争议,有些人认为,很多语言没用 undefined 也活的好好,为啥要 undefined 呢. 那有了 undefined 是否还需要 null 呢 ? typesc ...

  6. spring boot基于DRUID数据源密码加密及数据源监控实现

    前言 随着需求和技术的日益革新,spring boot框架是越来越流行,她也越来越多地出现在我们的项目中,当然最主要的原因还是因为spring boot构建项目实在是太爽了,构建方便,开发简单,而且效 ...

  7. Spring定时器的使用方法

    Spring定时器主要通过Quartz Cron表达式来实现定时任务,注解用法如下: # 每月的最后1天 @Scheduled(cron = "0 0 18 28–31 * ?") ...

  8. Ubuntu下设置静态网址

    百度上找的图形界面下设置方式: 因为我这里的ubuntu版本是14.10版本 所以我先点击[系统设置],它位置在桌面左侧的菜单栏后面位置. 在系统设置页面,找到[硬件]选项里面的[网络]一项 然后再使 ...

  9. 2.5 webpack 进阶

    配置分离 code splitting 异步加载 理解 webpack chunk webpack 调试 2.5.1 配置分离 在大型项目中,可能 webpack.config.js 会变得越来越臃肿 ...

  10. 在VMware软件下创建CentOs虚拟机

    1.创建新的虚拟机. 打开VMware软件,点击主页内创建新的虚拟机 2.进入新建虚拟机向导 点击典型,点击下一步 3.在下一步中单击稍后安装操作系统 点击下一步 4.选择操作系统类型 因为CentO ...