[TK] Blocks 单调栈
1.[TK] 矩阵取数游戏<简单版> hzoi-tg-906-22.[TK] 一心净士 hzoj-tg-937-23.[TK] 盖房子 hzoi-tg#2624.[TK] 三角蛋糕 hzoi-tg#2615.[TK] 选课 hzoj-tg#2796.[TK] 三色二叉树 hzoi-tg#282 存图方法7.[TK] HH的项链 离线树状数组解法8.[TK] 理想的正方形
9.[TK] Blocks 单调栈
10.[TK] 送礼物11.[TK] Terrible Prime12.[TK] BLO13.[TK] Rudolf and Subway ( CodeForces #933 div.3 - G )14.[TK] Bulls And Cows S15.[TK] 颜色16.[Tkey] 与非17.[TK] CF1526B I Hate 111118.[TK] 寻宝游戏19.[CL-22] 异或和之和20.联训题单 / 集训杂题纪要21.[At_dp_w] Intervals & [At_dp_x] Tower22.CF2023D - Many Games23.[NOI2021] 轻重边24.[CSP-S 2024] 染色题目描述
给出
初步分析
其实这个题与下述题目等效:
给出
我们来思考一下为什么两个问题会相等.
容易想到,只有平均数大于等于
因此,我们现在的问题就转化为,如何求这样的区间最大值.
区间最值
首先放出引理:若
根据此引理,我们定义有可能为最优解的条件:符合条件,且其左方没有符合条件的数.
所以,如果我们从左边遍历,遇到第一个符合条件的数,那么符合该条件的数只有它可能是最优解,所以我们直接改到下一个条件遍历.
总结出如下遍历步骤:
- 设定初始条件为
. - 从左向右尝试放入前缀和.
- 当前前缀和满足
,放入,并将 作为新的条件. - 不满足,忽略.
前缀和有正有负,那么为什么初始条件是
注意到此步骤可以用栈实现:
s.push(0);
for(int i=1;i<=n;++i){
sum[i]=sum[i-1]+a[i]-k;
if(sum[s.top()]>sum[id]){
s.push(id);
}
}
我们通过上述步骤,将栈内的内容维护成了一个严格单调递减的序列的下标,这样的话,只要满足
接下来我们来考虑如何求最大区间.
由上述引理,我们倒序遍历全部前缀和
代码实现
stack<long long> s;
long long a[1000001],sum[1000001];
void push(int id){
if(sum[s.top()]>sum[id]){
s.push(id);
}
}
long long calc(int n){
long long ans=0;
for(int i=n;i>=1;--i){
while(!s.empty()&&sum[i]-sum[s.top()]>=0){
ans=max(ans,i-s.top());
s.pop();
}
}
return ans;
}
int main(){
int n,m,k;
cin>>n>>m;
for(int i=1;i<=n;++i){
cin>>a[i];
}
for(int i=1;i<=m;++i){
cin>>k;
s.push(0);
for(int i=1;i<=n;++i){
sum[i]=sum[i-1]+a[i]-k;
push(i);
}
s.push(n);
cout<<calc(n)<<" ";
while(!s.empty()){
s.pop();
}
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!