[JZOJ6355] 【NOIP2019模拟】普
题目
题目大意
给你一个序列,对于所有k∈[1,n]k\in [1,n]k∈[1,n],求长度为kkk的子序列的最大权值,权值为a1−a2+a3−...±aka_1-a_2+a_3-...\pm a_ka1−a2+a3−...±ak
思考历程
这题显然可以背包对吧……
所以就直接背包吧……
比赛的时候我还想到了分治,但由于两边合在一起很慢,所以就直接打暴力了。
正解
题解的线段树做法看得并不是很懂。
所以我就说一个分治的方法。
首先题解有个结论:kkk的子序列必然是k−2k-2k−2的子序列中插入两个数。
记住是插入,而不仅仅是往左右两边扩展。
为什么呢?考虑反证,如果不是这样,就是k−2k-2k−2的子序列中除去若干个数,然后再插入若干的数。这样实际上相当于从k−xk-xk−x的状态转移过来,其中x>2x>2x>2。
所以我们只需要证明从k−2k-2k−2转移过来比更前面的地方转移过来更优。
假设从k−3k-3k−3转移过来(其它的情况类似)。
我们将k−2k-2k−2的序列中按顺序插入xxx和yyy,那么整个序列被分成几个部分AxByCAxByCAxByC,权值为A±x−B±y+CA\pm x-B\pm y+CA±x−B±y+C(我们不需要关系xxx和yyy的正负,BBB是原本的贡献,在插入之后符号要翻过来)。
将k−3k-3k−3的序列中插入xxx和yyy和zzz(我们假设xxx和yyy插入的位置相同),分成:AxByDzEAxByDzEAxByDzE,权值为A±x−B±y+D±z−EA \pm x-B \pm y+D \pm z-EA±x−B±y+D±z−E
比较一下,前半部分抵消了,就变成CCC和D±z−ED \pm z-ED±z−E
它们都可以看做一个整体。如果后面的更优,它肯定会在之前替代CCC。所以前者是更优一些的。
这就证完了。
然后考虑分治。分治的重点是合并左右两个区间的答案。
考虑由sss转移到s+2s+2s+2。设转移sss的时候左边用了s1s_1s1个,右边用了s2s_2s2个。
分类讨论看看新插入的两个点放哪边,就有如下三种情况:
- 左边s1+2s_1+2s1+2,右边s2s_2s2。
- 左边s1+1s_1+1s1+1,右边s2+1s_2+1s2+1
- 左边s1s_1s1,右边s2+2s_2+2s2+2.
根据上面的那个结论,前后两种情况是没有问题的。问题在于第二种情况。
由于是+1+1+1,所以就不能用那个结论。
然而,我们发现,在左边s1s1s1或右边s2s2s2的状态中各插一个,其实也算在左边s1+1s1+1s1+1或右边s2+1s2+1s2+1.的状态中。也就是说,s1+1s1+1s1+1的状态大于等于s1s1s1插一个转移过去的状态。
所以这样操作没有影响。
代码
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];elses1=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];elses1=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模拟】普相关推荐
- [JZOJ6355] 【NOIP2019模拟】普 24/100
题目 题目大意 给你一个序列,对于所有\(k\in [1,n]\),求长度为\(k\)的子序列的最大权值,权值为\(a_1-a_2+a_3-...\pm a_k\) 思考历程 这题显然可以背包对吧-- ...
- jzoj6355 【NOIP2019模拟】普(pe) (闵可夫斯基和)
分析 猜想一下这个函数是分奇偶凸的. 事实上也的确是这样. 考虑分治之后合并的过程.已经处理出了左右两边选多少个的最大值和最小值. 然后按照奇偶分类地合并即可得到新的值. 可以归纳地证明他是凸的.考虑 ...
- 6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]
题目 题目大意 有个无限长的数列an{a_n}an,a1=1a_1=1a1=1,an=an−1+maxdightk(an−1)a_n=a_{n-1}+maxdight_k(a_{n-1})an= ...
- 6360. 【NOIP2019模拟2019.9.18】最大菱形和(rhombus)
Description Input Output Sample Input 5 5 2 0 1 5 7 3 -4 2 0 -9 8 3 9 0 7 8 2 -4 5 -7 1 4 5 8 7 0 6 ...
- jzoj 6012.【NOIP2019模拟1.25A组】荷马史诗 dp
Description 追逐影子的人,自己就是shadow. --荷马 Shadow 最近迷上了文学.她喜欢在一个慵懒的午后,细细地品上一杯卡布奇诺,静静地阅读她爱不释手的<荷马史诗>.但 ...
- 6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]
题目 题目大意 给你一个数列,每次可以选择任意两个相邻的数xxx和yyy,将其删去,并在原来位置插入x+2yx+2yx+2y. 每次询问一个区间,对这个区间进行上述操作.求最后剩下的数最大是多少. 答 ...
- JZOJ6362. 【NOIP2019模拟2019.9.18】数星星(star)
Description Solution 考虑分治,将每一个询问挂在包括它的最大的区间中. 只考虑中点往右的区间的贡献,那么每一个点对于覆盖它的最早的时间有一个贡献. 我们建一个虚树,并且用并查集路径 ...
- 8.15.NOIP2019模拟赛总结——2019暑假篇
目录 一.题目 1.队列变换 1.1.题目描述 1.2.题解 1.3.Code 2.跨栏 2.1.题目描述 2.2.题解 2.3.Code 3.三角形 3.1.题目描述 3.2.题解 3.3.Code ...
- jzoj6384. 【NOIP2019模拟2019.10.23】珂学家
Description Input Output 输出共 行,每行一个非负整数表示答案. Sample Input 2 1 1 2 3 2 1 3 5 Sample Output 4 只能选用试剂1 ...
最新文章
- 《算法技术手册》一2.4.6 二次方的算法性能
- 何必分个孰优孰劣呢?!
- GET与POST可传递的最大值到底是多少?
- Linux redhat下安装jdk-6u45-linux-x64.bin
- 熟悉又陌生 彪悍徐茂栋的双面人生
- windows qt 不能debug_linux配置vlc-qt
- JAVA——附加作业2——情人节送花
- Retrofit2从入门到放弃
- cml sml区别_如何简单清晰地描述 CAPM 在投资学中的运用,以及 CAL、CML 和 SML 的关系和区别?...
- windows netcat的安装与使用
- ASP .NET中一个可以用来大作文章的地方。
- Win10下的Hp1020P打印机。
- popwindow的显示层面
- 微信收到消息很慢无法连接服务器,微信消息总是延迟接收怎么办?
- 桌面版docker安装搭建
- 千万不要点开,Cjson入门快速使用看这篇就够了(CJSON入门操作以及问题讲解,CJSON对象删除出错)
- python基础复习(30)--string[start:end:step] start默认0 end默认列尾 step默认1
- Codeforces div1+2
- FileSystemWatcher 用法
- CAD地形图!DWG格式的等高线地形图下载教程
热门文章
- jvm原理解析--不疯魔不成活
- 卷积网络中的通道(Channel)和特征图
- Unity3d 多线程、多并发网络解决方案(C#)
- 告别学习,步入社会【学习网络推广,emmm】
- 【DIY】多模式51单片机心形流水灯+呼吸灯+蜂鸣器音乐
- [书目20131223]Android、iPhone、Windows Phone手机网页及网站设计:最佳实践与设计精粹 - 张亚飞...
- win7 u盘 正在计算机,U盘在Win7电脑上读不出来怎么办?两种解决方法全教给你!...
- 测试成绩软件,软件部分测试成绩_精英 Z87H3-A3X_主板评测-中关村在线
- 一个小白的转行自学Python的经历
- 臧圩人:java面试题解惑系列(一)——类的初始化顺序学习笔记