博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[CF888E] Maximum Subsequence 序列分治
阅读量:5344 次
发布时间:2019-06-15

本文共 1399 字,大约阅读时间需要 4 分钟。

早期作品,不喜轻喷。

序列分治板子题。
切这道题用了好长时间,所以想发篇题解作为纪念 。
首先,我们认真观察题目数据(面向数据做题是个好习惯),发现题目的\(n\)竟然只有\(35\),我们顿时感到打暴力的机会来了:
\(2^n\)枚举?
是个好办法。
只可惜我们发现\(2^{35}=34359738368\),并不能过掉所有数据点,于是考虑优化。

分治

考虑把这\(n\)个数分成两组(当然要尽量平均),对两组数据分别实施暴力,并把结果存起来(事实上是可以存下来的:\(2^{18}=262144\))。

void dfs1(int i,int sum){    if(i==b){p[++k]=sum,p[++k]=(sum+a[b])%m; return ;}    dfs1(i+1,sum),dfs1(i+1,(sum+a[i])%m);}void dfs2(int i,int sum){    if(i==n){q[++t]=sum,q[++t]=(sum+a[n])%m; return ;}    dfs2(i+1,sum),dfs2(i+1,(sum+a[i])%m);}

这样一来,我们就得到了原序列分成两半的结果,这两个序列中的数两两组合就可以得到我们要的结果。

等等,两两组合?这样的复杂度不是和纯暴力一样吗?
这时候就需要我们贪心地看问题了:
我们发现:对于序列\(p\)中的每一个数\(p_i\),在序列\(q\)中若能找到一个与之相加小于\(m\)的最大的数\(q_j\),其他所有的与\(p_i\)的和小于\(m\)的数都不会比它更优,即\(q_j\)比序列\(q\)中所有比它小的数都更优。
对于\(q\)中的每一个数,满足相同条件的\(p_i\)也具有同样的性质。
我们想到一种对于\(p,q\)线性的算法:把\(p\)\(q\)排一遍序,把指向\(p\)数组的指针\(i\)和指向\(q\)数组的指针\(j\)分别按上面所说的条件向右和向左移动,同时更新\(ans\)
这时我们就只剩下\(p_i+q_j>m\)的情况了,由于在之前已经取过模,\(p_i+q_j\)必定小于\(2m\),所以我们就只需要用\(p,q\)的最大值之和去更新一下\(ans\)就好了。

代码实现

int main(){    R int i,j,ans=0;    n=read(),m=read(),b=n>>1;    for(i=1;i<=n;++i) a[i]=read();    if(n==1) printf("%d",a[1]%m),exit(0);    dfs1(1,0),dfs2(b+1,0),i=0,j=t;    sort(p+1,p+k+1),sort(q+1,q+t+1);    while(i<=k){        while(p[i]+q[j]>=m) --j;        ans=max(ans,p[i]+q[j]),++i;    }    ans=max(ans,p[k]+q[t]-m);    printf("%d",ans);    return 0;}

注意这里特判了一下\(n=1\)的情况,我被这个点坑了一次。

转载于:https://www.cnblogs.com/cj-chd/p/9981986.html

你可能感兴趣的文章
5.6.3.7 localeCompare() 方法
查看>>
Linux下好用的简单实用命令
查看>>
常用web字体的使用指南
查看>>
描绘应用程序级的信息
查看>>
poj2406-Power Strings
查看>>
2018/12/18 JS会像Linux一样改变编程
查看>>
php环境搭建脚本
查看>>
FTP主动模式与被动模式说明
查看>>
php 编译常见错误
查看>>
MES架构
查看>>
【Python3 爬虫】15_Fiddler抓包分析
查看>>
高性能JavaScript-JS脚本加载与执行对性能的影响
查看>>
关于标签之间因为换行等问题造成的空白间距问题处理
查看>>
hdu 2767(tarjan)
查看>>
sklearn之分类模型混淆矩阵和分类报告
查看>>
MySQL各存储引擎
查看>>
项目--简单导出CSV文件
查看>>
Oracle session相关数据字典(一)
查看>>
织梦文章内容提取第一张或者多张图片输出
查看>>
C#用正则表达式 获取网页源代码标签的属性或值
查看>>