题目描述
一个含有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
最后祝大家,大吉大利,今晚吃鸡啊哈。
一世安宁
来源:oschina
链接:https://my.oschina.net/u/4390709/blog/3976152