博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[POI2010]Blocks
阅读量:6833 次
发布时间:2019-06-26

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

题目大意:

  给你一个长度为n的数列,给你m个数k。
  对于每个k,你可以进行若干次操作,每次把一个超过k的数的多余部分移到旁边一个数。
  问对于每个k,进行若干次操作以后,最长的满足每个数都不小于k的区间长度。

思路:

  一个区间可以通过若干次操作使得每个数都不小于k,当且仅当这个区间平均数大于等于k。
  对于每个k,我们可以先O(n)求出这个序列每个数减去k的前缀和。
  对于i>j,如果sum[i]>=sum[j],那么对于i之后的数,用i转移肯定比j更优。
  因此我们可以维护一个关于前缀和的单调递减栈。
  然后枚举区间的右端点,在单调栈中找到最左的满足前缀和之差大于等于0的左端点即可。

1 #include
2 #include
3 #include
4 typedef long long int64; 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');10 return x;11 }12 const int N=1000001;13 int a[N];14 int64 sum[N];15 std::stack
s;16 int main() {17 const int n=getint(),m=getint();18 for(register int i=1;i<=n;i++) {19 a[i]=getint();20 }21 for(register int i=1;i<=m;i++) {22 const int k=getint();23 s.push(0);24 for(register int i=1;i<=n;i++) {25 sum[i]=sum[i-1]+a[i]-k;26 if(sum[i]
=sum[s.top()]) {32 j=s.top();33 s.pop();34 }35 ans=std::max(ans,i-j);36 }37 printf("%d%c",ans," \n"[i==m]);38 while(!s.empty()) s.pop();39 }40 return 0;41 }

 

转载于:https://www.cnblogs.com/skylee03/p/8183776.html

你可能感兴趣的文章
K8S网络NAT问题分析与处理
查看>>
XStream处理重复的或循环引用
查看>>
对某机构为“转移内部矛盾”而嫁祸于我们的事件之真相大起底
查看>>
Exchange管理控制台无法安装,要求重新启动
查看>>
【案例分享】电力设备生产数据的多层分组统计报表实现
查看>>
Windows 7下安装Cygwin亲历烦恼记录
查看>>
4G时代,语音社交APP或成智能手表的杀手级应用
查看>>
年入十万靠努力,年入百万靠能力,年入千万靠什么
查看>>
【免费下载】《这样理解知识管理》电子书,2016学会知识管理
查看>>
轻量级的Web服务器Nginx0.9.0 开发版发布
查看>>
听到两个程序员聊天——A:“借我1K块。”
查看>>
Oracle ROWID
查看>>
重构可让SQL提高可维护性,可读性以及效能性
查看>>
java多线程例子
查看>>
fabric自动部署
查看>>
linux 命令小抄
查看>>
前端必读:浏览器内部工作原理
查看>>
C Socket Programming for Linux with a Server and Client Example Code
查看>>
6天通吃树结构—— 第一天 二叉查找树
查看>>
vs2005/vs2008和sql2005 的安装顺序
查看>>