Luogu-P1886 滑动窗口

眉间皱痕 提交于 2019-11-27 10:19:51

 

题目

题目链接

 

 

测试得分:  100

 

 

主要算法 :  单调队列优化DP

 

 

题干:

  单调队列优化DP板子

 分析

  单调队列优化DP定长连续区间最值问题

  代码

 

#include<stdio.h>  #include<stdlib.h>  #define FORa(i,s,e) for(int i=s;i<=e;i++)  #define FORs(i,s,e) for(int i=s;i>=e;i--)  #define gc getchar()//pa==pb&&(pb=(pa=buf)+fread(buf,1,100000,stdin),stdin)?EOF:*pa++  #define File(name) freopen(name".in","r",stdin);freopen(name".out","w",stdout);    using namespace std;  char buf[100000],*pa,*pb;  inline int read();    const int N=1e6,K=1e6;  int n,k,a[N+1];    int head,tail,num[K+1],q[N+1];  /*单调队列,num[]记录的是单调队列中元素在输入数据中的编号,q代表的是元素在输入数据中的值*/  void Solve_Min()  {      head=1,tail=0;      FORa(i,1,n)      {          while(head<=tail&&a[i]<q[tail]) tail--;          /*如果发现单调队列中(简单的说就是这个框中的所有元素)有比现在还大的,全部删除          删除理由是单调性性质,这个答案对于后面没有贡献了,因为现在这个即将插入的元素即将做出贡献          做的贡献越多而且做贡献的次数也绝对不低于这些删除的元素            */           q[++tail]=a[i],num[tail]=i;          //将元素插入队列           while(num[head]<i-k+1) head++;//如果单调队列中首尾元素的差值超过了框的长度,推进头指针           if(i>=k) printf("%d ",q[head]);//满足条件输出       }      printf("\n");  }  void Solve_Max()  {      head=1,tail=0;      FORa(i,1,n)      {          while(head<=tail&&a[i]>q[tail]) tail--;          q[++tail]=a[i];          num[tail]=i;          while(num[head]<i-k+1) head++;          if(i>=k) printf("%d ",q[head]);      }  }    int main()  {      n=read(),k=read();      FORa(i,1,n) a[i]=read();      Solve_Min(),Solve_Max();      return 0;  }  inline int read()  {      register char c(gc);register int f(1),x(0);      while(c<'0'||c>'9') f=c=='-'?-1:1,c=gc;      while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=gc;      return x*f;  }

总结:

   确定动规模型

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!