题目描述
一个含有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输出‘ ’比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<<" "; 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 "); 12 for(int i=2; i<=n; i++) { 13 printf("%d ",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
最后祝大家,大吉大利,今晚吃鸡啊哈。
一世安宁