题目链接:点击查看

题目分析:给出 nnn 个数,定义滑动窗口的贡献是其中最大值与最小值的乘积,现在问对于长度分别为 [1,n][1,n][1,n] 的滑动窗口,贡献之和分别是多少

题目分析:考虑暴力解法,是直接 RMQRMQRMQ 预处理一下,然后 O(n2)O(n^2)O(n2) 去模拟整个过程

正难则反,考虑正这去枚举区间不行,那么我们是否可以通过枚举每个数字,从而计算每个数字对区间的贡献呢

根据滑动窗口的定义,不难发现在每个长度下的滑动窗口,对于每个位置来说,都有可能作为一次窗口的起点或终点(如果越界的话有时候某些位置是无法满足条件的)

按照官方题解的思路,就是是去枚举 nnn 个位置作为滑动窗口的终点,我们记为 rrr,然后利用单调栈去维护一下最值,这样就可以将区间 [1,r][1,r][1,r] 划分成数个连续的区间,满足所有的区间拼接起来就是总区间 [1,r][1,r][1,r]。对于划分后的某段区间 [x,y][x,y][x,y] 来说,满足 i∈[x,y]i\in[x,y]i∈[x,y],区间 [i,r][i,r][i,r] 的最大值和最小值是相同的。这样滑动窗口的长度属于 [r−y+1,r−x+1][r-y+1,r-x+1][r−y+1,r−x+1] 的贡献加上相应的乘积即可。区间更新最后统一查询,这里我选择使用的是差分数组

最后就是复杂度该如何证明呢,由于本题 aia_iai​ 的上限是 100100100,所以单调栈中维护的元素最多不可能超过 100100100 个,由于同时需要维护两个单调栈分别维护最大值和最小值,所以拼接起来划分的区间最多也是 100+100=200100+100=200100+100=200 个,也就是说每次最多会将区间 [1,r][1,r][1,r] 划分成 200200200 个子区间,利用差分暴力更新即可,时间复杂度 O(n∗max(ai)∗2)O(n*max(a_i)*2)O(n∗max(ai​)∗2)

代码:

// Problem: 牛牛的滑动窗口
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/7604/D
// Memory Limit: 524288 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)// #pragma GCC optimize(2)
// #pragma GCC optimize("Ofast","inline","-ffast-math")
// #pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#define lowbit(x) x&-x
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
template<typename T>
inline void read(T &x)
{T f=1;x=0;char ch=getchar();while(0==isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(0!=isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();x*=f;
}
template<typename T>
inline void write(T x)
{if(x<0){x=~(x-1);putchar('-');}if(x>9)write(x/10);putchar(x%10+'0');
}
const int inf=0x3f3f3f3f;
const int N=1e6+100;
int a[N],ans[N],mitp,mxtp;
struct Node {int val,pos;
}mi[N],mx[N];
void add(int l,int r,int val) {ans[l]+=val;ans[r+1]-=val;
}
int main()
{#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n;read(n);for(int i=1;i<=n;i++) {read(a[i]);}for(int i=1;i<=n;i++) {while(mitp&&mi[mitp].val>=a[i]) {mitp--;}while(mxtp&&mx[mxtp].val<=a[i]) {mxtp--;}int mmax=a[i],mmin=a[i],pos=i,tp1=mitp,tp2=mxtp;while(tp1||tp2) {if(tp1&&tp2) {if(mi[tp1].pos>=mx[tp2].pos) {add(i-pos+1,i-mi[tp1].pos,mmin*mmax);mmin=mi[tp1].val;pos=mi[tp1].pos;tp1--;} else {add(i-pos+1,i-mx[tp2].pos,mmin*mmax);mmax=mx[tp2].val;pos=mx[tp2].pos;tp2--;}} else if(tp1) {add(i-pos+1,i-mi[tp1].pos,mmin*mmax);mmin=mi[tp1].val;pos=mi[tp1].pos;tp1--;} else if(tp2) {add(i-pos+1,i-mx[tp2].pos,mmin*mmax);mmax=mx[tp2].val;pos=mx[tp2].pos;tp2--;}}add(i-pos+1,i,mmin*mmax);mx[++mxtp]={a[i],i};mi[++mitp]={a[i],i};}for(int i=1;i<=n;i++) {ans[i]+=ans[i-1];printf("%d ",ans[i]);}return 0;
}

牛客 - 牛牛的滑动窗口(单调栈+思维+差分)相关推荐

  1. 牛客题霸 [滑动窗口的最大值] C++题解/答案

    牛客题霸 [滑动窗口的最大值] C++题解/答案 题目描述 给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值.例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一 ...

  2. 牛客 奇怪的排序问题(单调栈/遍历)

    文章目录 1. 题目 2. 解题 1. 题目 链接:https://ac.nowcoder.com/acm/contest/10166/B 来源:牛客网 操场上有n个人排成一队,这n个人身高互不相同, ...

  3. 2021牛客多校2 - Stack(单调栈+拓扑)

    题目链接:点击查看 题目大意:给出 b[i]b[i]b[i] 数组的求解过程: Stk is an empty stack for i = 1 to n :while ( Stk is not emp ...

  4. 牛客小白月赛13-H(单调栈+树状数组)

    题目链接:https://ac.nowcoder.com/acm/contest/549/H 题意:给一个柱状图,包括每个矩阵的宽度和高度,求能组成的最大矩阵的面积. 思路:显然最大矩阵的高一定为n个 ...

  5. 牛客 小米校招 计算题 单调栈 接雨水

    给定n个非负整数表示每个宽度为1的柱子的高度题,计算按此排列的柱子,下雨之后能接多少雨水. 经典的题目 leetcode 42 接雨水 单调栈 保持栈内单调递减 每次把一个矮的出栈都能够加上一大块面积 ...

  6. 【牛客网】滑动窗口的最大值

  7. 入门经典_Chap08_题解总结:极角扫描法 滑动窗口 单调队列 单调栈

    总结  本章主要关注一个重要的问题 – 单调队列和单调栈的使用  同时还有一些其他的问题,如扫描法,递归的思想, 构造, 分治, 二分等 知识点 单调队列 和 单调栈 题目 UVA - 1606 Am ...

  8. 牛客竞赛语法入门班数组栈、队列和stl习题

    牛客竞赛语法入门班数组栈.队列和stl习题 L 指纹锁 set ,自带排序功能 可重写排序函数 cmp,注意外边写的要写成 operator()operator()operator(),结构体内部的排 ...

  9. 单调栈思维 2021年度训练联盟热身训练赛第三场——K题 Summer Trip

    题意: 给你一个字符串,问其子串中有多少个满足: 1.子串头尾字母不相同: 2.子串内部字母与头尾字母不相同: 3.子串长度大于等于2: 问有多少个这样的字串? 题目: Leo has started ...

最新文章

  1. 按计算机的地位划分计算机网络可分为,2010年全国自考计算机网络基本原理模拟试卷(三)及答案...
  2. 一个好域名的作用和价值
  3. macbook和 windows共享文件
  4. [数据结构与算法]平衡二叉树实现
  5. c#读蓝牙数据_客户端实现蓝牙接收(C#)知识总结
  6. 【深度强化学习】DQN训练超级玛丽闯关
  7. 图像像素灰度内插(Matlab实现)
  8. 前端学习(1677):前端系列实战课程之游戏初始化
  9. 20154319 《网络对抗技术》后门原理与实践
  10. 表面粗糙度的基本评定参数是_表面粗糙度100问,讲得明明白白
  11. linux强制删除后登录不了,【已解决】更新之后无法登录
  12. linux make 无法生成 .o gch,Linux--makefile的使用
  13. AcWing 836. 合并集合
  14. vmware硬件兼容官方查询地址
  15. 联想微型计算机a20,联想乐player A20
  16. 遗传算法matlab_【优化求解】遗传算法解决背包问题
  17. 细粒度分类网络之WS-DAN论文阅读附代码
  18. 摄影测量学习总结(较全面易懂)
  19. authorize.AuthorizationException: User: livy is not allowed to impersonate
  20. ubuntu安装windows 字体

热门文章

  1. 编写登录成功和失败的处理器
  2. 初识ES-安装IK分词器
  3. Gateway网关-快速入门
  4. 初步认识Volatile-总线锁和缓存锁
  5. AutoConfigurationImportSelector是什么?
  6. 字节流读数据(一次读一个字节数据)
  7. aop简介-基于jdk的动态代理
  8. Spring 的创建流程
  9. 记一次CentOS Install Docker 报错
  10. mac要装anaconda吗_Anaconda安装教程|Windows,Linux ,Mac OS