洛谷 1440 求m区间内的最小值

早过忘川 提交于 2020-05-08 03:10:10

            洛谷  1440 求m区间内的最小值

题目描述

一个含有n项的数列(n<=2000000),求出每一项前的m个数到它这个区间内的最小值。若前面的数不足m项则从第1个数开始,若前面没有数则输出0。

输入输出格式

输入格式:

第一行两个数n,m。

第二行,n个正整数,为所给定的数列。 

输出格式:

n行,第i行的一个数ai,为所求序列中第i个数前m个数的最小值。

题解:

偷偷告诉你,我超级喜欢暴力的。所以看到这个题的第一反应,就是打暴力

 1 // luogu-judger-enable-o2
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<cmath>
 7 using namespace std;
 8 int a[2000010],n,m;
 9 int main(){
10     scanf("%d%d",&n,&m);
11     for(int i=1;i<=n;i++)
12         scanf("%d",&a[i]);
13     cout<<0<<endl;
14     for(int i=2;i<=n;i++){
15         int s=i-m,minn=999999999;
16         if(s<1)
17             s=1;
18         for(int j=s;j<i;j++)
19             minn=min(minn,a[j]);
20         cout<<minn<<endl;
21     }
22     return 0;
23 }

hhh,没想到,居然有50分;

next,我还是想不出正解,因为那时候刚学队列然而我对队列无感,对于讲队列的学长更是,emmm。在这里吐槽一句,他的代码实在是太丑了。

然后,我就开始想方设法,为所欲为的给它提速,然后加了一个特判

 

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int a[2000010],n,m,minn=999999999,minp;
 8 int main(){
 9     scanf("%d%d",&n,&m);
10     for(int i=1; i<=n; i++)
11         scanf("%d",&a[i]);
12     cout<<0<<endl;
13     for(int i=2; i<=n; i++){
14         int s=i-m;
15         if(s<1) s=1;
16         if(a[i-1]<=minn) minn=a[i-1],minp=i-1;
17         if(minp<s){
18             minn=a[s],minp=s;
19             for(int j=s; j<i; j++)
20                 if(a[j]<=minn) 
21                     minn=a[j],minp=j;
22         }
23         cout<<minn<<endl;
24     }
25     return 0;
26 }

 

然后,居然70了,哇,amazing。

最后呢,听一位学长说,cout输出‘\n’比printf或者输出endl快,就试了一哈子。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<cmath>
 6 using namespace std;
 7 int a[2000010],n,m,minn=999999999,minp;
 8 int main(){
 9     scanf("%d%d",&n,&m);
10     for(int i=1; i<=n; i++)
11         scanf("%d",&a[i]);
12     cout<<0<<endl;
13     for(int i=2; i<=n; i++){
14         int s=i-m;
15         if(s<1) s=1;
16         if(a[i-1]<=minn) minn=a[i-1],minp=i-1;
17         if(minp<s){
18             minn=a[s],minp=s;
19             for(int j=s; j<i; j++)
20                 if(a[j]<=minn) 
21                     minn=a[j],minp=j;
22         }
23         cout<<minn<<"\n";
24     }
25     return 0;
26 }

这样居然A了,简直了。

不过呢,还是要尊重正解。

 1 #include<complex>
 2 #include<cstdio>
 3 using namespace std;
 4 const int N=2e6+7;
 5 int n,m,head=1,tail,a[N],q[N];
 6 int main() {
 7     scanf("%d%d",&n,&m);
 8     for(int i=1; i<=n; i++)
 9         scanf("%d",&a[i]);
10     q[++tail]=1;
11     printf("0\n");
12     for(int i=2; i<=n; i++) {
13         printf("%d\n",a[q[head]]);
14         if(q[head]<=i-m)head++;
15         while(head<=tail && a[q[tail]]>=a[i])
16             tail--;
17         q[++tail]=i;
18     }
19     return 0;
20 }

正解是队列。

题目说完了,进入吐槽时间。

吐槽:

 

讲队列的那位学长真的是,我第一次听他讲课的时候还没有感觉他长的那么惨无人道,惨绝人寰。现在真是越看越,emmm。话说他给我们布置的题目,说是用队列做的,我全没用队列,全用的暴力诶,哎也不是不想写队列,emmm,不会啊,现在更是好久没复习队列了,感觉队列和栈都快分不清楚了。哎,看来我有必要继续颓废了。hhh

最后祝大家,大吉大利,今晚吃鸡啊哈。

一世安宁

 

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