题目

题目大意

给你一个数列,每次可以选择任意两个相邻的数xxx和yyy,将其删去,并在原来位置插入x+2yx+2yx+2y。
每次询问一个区间,对这个区间进行上述操作。求最后剩下的数最大是多少。
答案需要取模。


思考历程

看到这题,第一个想法是:这题既要搞个最大值,又要取模,所以肯定是贪心。
然而不会……
O(n3)O(n^3)O(n3)的暴力是可以打的,直接区间DPDPDP。然而我没有打。
其实最大的瓶颈是,我需要比大小,然而数太大,会炸掉……
这题题面本身就对暴力不友好……


正解

其实我比赛的时候就发现了一个有趣的性质:
我们把操作看成整个区间分成两个区间,后面的那个区间的系数乘二,然后两边继续递归下去处理。
容易发现,假设2……ki2……{k_i}2……ki​为第iii项的系数,则1≤ki≤ki−1+11\leq k_i \leq k_{i-1}+11≤ki​≤ki−1​+1,k1=0k_1=0k1​=0
可以把答案序列看成几个kik_iki​的等差数列,每个等差数列的开头都是111到前一个的结尾(第一个等差数列除外)。

然而有个更加神奇的结论:kik_iki​要么是111,要么就是ki−1+1k_{i-1}+1ki−1​+1
简单地证明一下:
对于一个等差数列,记一下它的和。如果和大于等于000,则将它接到前面一个等差数列后面会更优;如果小于000,则将开头的kkk设为111最优。

先不要考虑所有的询问。假设询问从111开始,增量法构造这些等差数列。
首先新增一个节点,kik_iki​为111,然后试着跟前面合并。
如果大于等于000,就接到前面去。接了之后试着继续跟前面合并。
否则就不接到前面去。
显然这样是没有问题的。

接下来考虑如何处理区间的询问。先离线一下,按照区间右端点排序,询问挂在右端点上。
在统计答案的时候,找到左端点所在等差数列。找的时候可以二分或者并查集。
左端点所在等差数列的后面那些等差数列的和直接加起来。可以用前缀和实现。
左端点可能会将等差数列分成两部分,直接计算后面的那一块就好了。计算的时候可以一开始就预处理sumi=∑j=1i2jajsum_i=\sum_{j=1}^{i}2^ja_jsumi​=∑j=1i​2jaj​,后面的sumsumsum减去suml−1sum_{l-1}suml−1​,再除以2l2^l2l。

为什么分割之后等差数列不会变呢?
其实只需要证明后面的不会合并上来,并且这个也不会继续分裂就行了。
后面的和肯定是负数,所以前面的变了它们也不会合并上来。
如果这个分裂了(假设分裂成BBB和CCC,分割处左边的为AAA),原来的和为A+2xB+2x+yCA+2^xB+2^{x+y}CA+2xB+2x+yC,在分割之后和变成B+2yCB+2^yCB+2yC。如果它分裂了,就变成B+CB+CB+C.。
各自乘上2x2^x2x,加上AAA,就分别变成了A+2xB+2x+yCA+2^xB+2^{x+y}CA+2xB+2x+yC和A+2xB+2xCA+2^xB+2^xCA+2xB+2xC
由于前者一定是最优的,所以2yC≥C2^yC\geq C2yC≥C,所以C>0C>0C>0。
所以它分裂了不会更优。

在实现的时候,它很容易爆掉long long。实际上,虽然正数很大,但是它最小的负数不会太小。因为在最小的时候,一定是某个等差数列中只有一个负数(如果有几个数从后面合并上来,后面的那几个数的和一定非负数,然后和不会更小)。所以最小是−2e9-2e9−2e9。
如果有个数大于2e92e92e9,说明它以后永远不会变成负数。记作2e9+12e9+12e9+1就行了。
实现的时候要记录一个真的和,用来计算答案(有模);记录一个假的和,用来比大小。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 500010
#define ll long long
#define INF 2000000000
#define mo 1000000007
inline ll my_pow(ll x,int y){ll res=1;for (;y;x=x*x%mo,y>>=1)if (y&1)res=res*x%mo;return res;
}
int n,m;
int a[N];
struct Query{int l,r,num;
} q[N];
inline bool cmpq(Query a,Query b){return a.r<b.r;}
ll ans[N];
ll _2,pow2[N],ipow2[N],bpow2[N],g[N];
int st[N],top;
ll sum[N],rs[N],pre[N];
int main(){freopen("border.in","r",stdin);freopen("border.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=n;++i)scanf("%d",&a[i]);_2=my_pow(2,mo-2);pow2[0]=bpow2[0]=ipow2[0]=1;for (int i=1;i<=n;++i){pow2[i]=pow2[i-1]*2%mo;bpow2[i]=bpow2[i-1]*2;bpow2[i]=(bpow2[i]>INF?INF+1:bpow2[i]);ipow2[i]=ipow2[i-1]*_2%mo;g[i]=(g[i-1]+pow2[i]*a[i])%mo;}for (int i=1;i<=m;++i)scanf("%d%d",&q[i].l,&q[i].r),q[i].num=i;sort(q+1,q+m+1,cmpq);st[top=1]=1,pre[1]=sum[1]=rs[1]=a[1];int j=1;for (;q[j].r<=1;++j)ans[q[j].num]=(a[1]+mo)%mo;for (int i=2;i<=n;++i){st[++top]=i;sum[top]=2*a[i];rs[top]=2ll*(a[i]+mo)%mo;while (top>1 && sum[top]>=0){rs[top-1]=(rs[top-1]+rs[top]*pow2[st[top]-st[top-1]-(top==2)])%mo;sum[top-1]=sum[top-1]+sum[top]*bpow2[st[top]-st[top-1]-(top==2)];sum[top-1]=(sum[top-1]>INF?INF+1:sum[top-1]);top--;}pre[top]=(pre[top-1]+rs[top])%mo;st[top+1]=i+1;for (;j<=m && q[j].r<=i;++j){int l=2,r=top,x=1;while (l<=r){int mid=l+r>>1;if (st[mid]<=q[j].l)l=(x=mid)+1;elser=mid-1;}ans[q[j].num]=((pre[top]-pre[x]+mo)+(g[st[x+1]-1]-g[q[j].l-1])*ipow2[q[j].l]%mo+mo)%mo;}}for (int i=1;i<=m;++i)printf("%lld\n",ans[i]);return 0;
}

总结

感觉自己太菜了……
面对贪心的题,一定要敢于下结论……

6374. 【NOIP2019模拟2019.10.04】结界[生与死的境界]相关推荐

  1. 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​= ...

  2. JZOJ6384【NOIP2019模拟2019.10.23】珂学家

    珂学家 题目描述: 输入: 输出: 输出共mmm行,每行一个非负整数表示答案. 这道题看到是一个区间,便想到了数据结构之类的东西. 但是呢它好像不带修.所以初步判断这是个离线的题目. 再仔细观察发现, ...

  3. jzoj6384. 【NOIP2019模拟2019.10.23】珂学家

    Description Input Output 输出共 行,每行一个非负整数表示答案. Sample Input 2 1 1 2 3 2 1 3 5 Sample Output 4 只能选用试剂1 ...

  4. jzoj6377. 【NOIP2019模拟2019.10.05】幽曲[埋骨于弘川]

    题解 真的都快忘了. 首先,我们考虑排序,求出一个神奇的排列方式,也就是dfn序. 那么答案必定是在dfn序里面一些连续的段连接起来. 然后我们就判断这玩意儿是否满足在a里面出现过. 于是现在分两步走 ...

  5. 【日常训练】2019-10-24am_xjoi结界[生与死的境界]/codeforces878E_贪心

    题面 现场题面 codeforces878E codeforces878E A sequence of n integers is written on a blackboard. Soon Sash ...

  6. 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 ...

  7. JZOJ6362. 【NOIP2019模拟2019.9.18】数星星(star)

    Description Solution 考虑分治,将每一个询问挂在包括它的最大的区间中. 只考虑中点往右的区间的贡献,那么每一个点对于覆盖它的最早的时间有一个贡献. 我们建一个虚树,并且用并查集路径 ...

  8. 野鸡NOI.AC模拟赛【2019.10.26】

    前言 截止至2019.10.2614:222019.10.26\ \ \ \ 14:222019.10.26    14:22 成绩 正题 T1:NOI.AC−T1:NOI.AC-T1:NOI.AC− ...

  9. 2019.10.26日常总结兼一码学成普及模拟4比赛选解

    [题目A]: [题目]: 有 n 只袋鼠(题目假设他们都是母的),你需要给他们组建成家庭. 对于第 i 只袋鼠来说,它的大小用一个数字 Si 来表示. 如果第 i 只袋鼠的大小 Si 达到了第 j 只 ...

最新文章

  1. 实验LVS+keepalived
  2. java安全插件_如何安全地实现Java插件安全性?
  3. IIS 7 应用程序池自动回收关闭的解决方案
  4. Makefile之大型工程项目子目录Makefile的一种通用写法
  5. linux中的nm命令
  6. 【小白学习C++ 教程】九、C++中字符型、字符串和转义字符
  7. ASP.NET实现下载的中文文件名乱码处理
  8. 如何在 ASP.Net Core 中使用 NCache
  9. 复制书稿(信息学奥赛一本通-T1278)
  10. 2012,新的一年,新的开始
  11. JavaScript 继承
  12. 反卷积(转置卷积)的理解
  13. java中cleanup的使用_Eclipse使用代码清理功能(Clean Up)
  14. python json dump_为什么json.dump()没有以\ n结尾? - python
  15. 入口函数ufusr()与ufsta()的区别
  16. 什么才是成熟的爱——爱的四个层次
  17. 华为p50预计售价鸿蒙是什么,华为p50预计售价多少_华为p50售价预估
  18. 计算机屏幕方向变化,知识:如何切换笔记本电脑屏幕的方向_计算机的基本知识_IT /计算机_信息...
  19. 软技能-代码之外的生存指南读后感 自我营销篇
  20. LXC的Python学习笔记

热门文章

  1. python分析红楼梦中人物形象_分析红楼梦中你喜欢的人物形象
  2. xshell调用js脚本开发
  3. win10dnf服务器未响应,win101903玩DNF卡顿 ,掉线,死机的解决办法
  4. [Redis实战]单文件夹启动多实例,redis哨兵+主从复制完整demo样例[windows环境]
  5. 索尼机型刷机不用愁 带你玩转一键解锁
  6. APS计划排产软件助家纺企业进行成本控制
  7. 百万调音师—Audition多轨编辑
  8. 【Spring Boot】--整合RabbitMQ
  9. request:fail -202:net::ERR_CERT_AUTHORI
  10. 【YOLOv1原文+翻译】You Only Look Once Unified, Real-Time Object Detection