今天老师请了前几届的学长来讲课,可是讲课为什么要考试呢...

  学长说难度是NOIP,于是我就naive的跟着参加了,然而T3难度并不友好,感觉确实不是很适合我们现在做......不过课本来也不是给我们这一届讲的?好像逻辑非常自洽的样子。

  T1:签到题

  题意概述:从一个长度为n的序列中选出一个长度为k的子序列,使得子序列的字典序最大。$n<=1.5*10^7,k<=10^6$

  本来想的是一个二维的dp,然而数组开不下,这时候我看向了题目名称:“签到题”,并没有意识到出题人的用意的我坚信这是一道简单题,就真的想出来了...

  因为字典序是从前往后比较,如果一个数大后面的就不用再比了,有种贪心的感觉,如果一个数大,就一直往前放,这样不就可以了吗?维护一个单调栈,按照顺序往里面加数,不过还要考虑一个问题,如果这个数虽然非常大,但是太靠后了以至于把它作为第一个后面就无法选出k个数了,那不就....但是还是非常好改的,根据每一个点后面有几个点处理出它最早能插入到哪里就好了。(这个问题竟然是对拍才发现的qwq

  
 1 # include <cstdio>
 2 # include <iostream>
 3 # define R register int
 4 
 5 using namespace std;
 6 
 7 int Top,x,y,z,n,k;
 8 int a[15000009];
 9 int q[1000009];
10 
11 void ins (int x)
12 {
13     while (Top>0&&q[Top]<a[x]&&n-x>=k-Top) Top--;
14     q[++Top]=a[x];
15 }
16 
17 int main()
18 {
19     freopen("red.in","r",stdin);
20     freopen("red.out","w",stdout);
21     
22     scanf("%d%d%d%d%d",&x,&y,&z,&n,&k);
23     a[1]=x;
24     for (R i=2;i<=n;++i)
25         a[i]=(long long)a[i-1]*y%z+1;
26     for (R i=1;i<=n;++i)
27         ins(i);
28     for (R i=1;i<=k;++i)
29         printf("%d\n",q[i]);
30 
31     fclose(stdin);
32     fclose(stdout);
33     return 0;
34 }
red

相关文章: