LOJ#541. 「LibreOJ NOIP Round #1」七曜圣贤

有一辆车一开始装了编号0-a的奶茶,现有m次操作,每次操作Pi在[-1,b),若Pi为一个未出现过编号的奶茶,就把他买了并装上车;若Pi为一个在车上的奶茶,则把他丢下车;否则,此次操作为捡起最早丢下去的奶茶,若没有符合要求的奶茶则忽略此次操作。对每次操作需要在线询问:操作进行后,不在车上的奶茶的最小编号。m<=1e6,b<=2m,a<=m,数据组数T<=50。

方法一:nlogn暴力,什么树状数组优先队列尽管上。。

方法二:不在车上的最小编号,其实就是还没买的最小和丢下车的最小,还没买的最小可以一个队列搞定,那丢下车的呢?由于先丢下车的会先捡起来,也就是先退出答案考虑的范围,如果某个奶茶又是早丢下车的,编号又不如一个后丢下车的小,那在这个奶茶退出答案前的整个过程他都不会再被当做答案。所以对丢下车的,用一个普通队列记顺序,一个单调队列记答案即可。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<math.h>
  5 #include<algorithm>
  6 //#include<iostream>
  7 using namespace std;
  8 
  9 namespace IO{
 10     int c;
 11     unsigned int seed;
 12     unsigned int randnum(){
 13         seed^=seed<<13;
 14         seed^=seed>>17;
 15         seed^=seed<<5;
 16         return seed;
 17     }
 18 
 19     inline int read(int &x){scanf("%d",&x);return x;}
 20     inline void init_case(int &m,int &a,int &b,int &d,int p[]){
 21         scanf("%d%u%d%d%d%d",&m,&seed,&a,&b,&c,&d);
 22         for(int i=1;i<=m;i++){
 23             if(randnum()%c==0)p[i]=-1;
 24             else p[i]=randnum()%b;
 25         }
 26     }
 27 
 28     inline void update_ans(unsigned int &ans_sum,unsigned int cur_ans,int no){
 29         const static unsigned int mod=998244353;
 30         ans_sum^=(long long)no*(no+7)%mod*cur_ans%mod;
 31     }
 32 }
 33 using IO::read;
 34 using IO::init_case;
 35 using IO::update_ans;
 36 /*
 37 一开始请调用read(T)读入数据组数T
 38 接下来每组数据开始时请调用init_case(m,a,b,d,p)读入m,a,b,d,p[]
 39 每组数据开始时请用一个初始化为0的32位无符号整形变量ans_sum存储答案,然后对于每个i,
 40 用32位无符号整形变量cur_ans存储第i次答案,并调用update_ans(ans_sum,cur_ans,i)更新。最后输出ans_sum即可。
 41 */
 42 
 43 //示例代码:
 44 int n;
 45 #define maxn 2000011
 46 unsigned int qin[maxn],headin,tailin,qout[maxn],headout,tailout,q[maxn],head,tail;bool buy[maxn],have[maxn];
 47 int main()
 48 {
 49     static int p[2000005];
 50     int T;read(T);
 51     int m,a,b,d;
 52     while(T--)
 53     {
 54         unsigned int ans_sum=0,cur_ans=0;
 55         init_case(m,a,b,d,p);
 56         
 57         memset(buy,0,sizeof(buy));
 58         memset(have,0,sizeof(have));
 59         headin=tailin=headout=tailout=head=tail=0;
 60         for (int i=0;i<=a;i++) buy[i]=have[i]=1;
 61         for (int i=a+1;i<=2*m;i++) qin[tailin++]=i;
 62         
 63         for(int i=1;i<=m;i++)
 64         {
 65             if (d)
 66             {
 67                 if (p[i]==-1) cur_ans=0;
 68                 else if (!buy[p[i]])
 69                 {
 70                     buy[p[i]]=have[p[i]]=1;
 71                     while (buy[qin[headin]]) headin++;
 72                     cur_ans=qin[headin];
 73                     if (headout<tailout) cur_ans=min(cur_ans,qout[headout]);
 74                 }
 75                 else cur_ans=0;
 76             }
 77             //d=1 hai mei pan duan 
 78             else if (p[i]<0)
 79             {
 80                 if (head==tail) cur_ans=0;
 81                 else
 82                 {
 83                     have[q[head]]=1;
 84                     if (qout[headout]==q[head]) headout++;
 85                     head++;
 86                     cur_ans=qin[headin];
 87                     if (headout<tailout) cur_ans=min(cur_ans,qout[headout]);
 88                 }
 89             }
 90             else if (!buy[p[i]])
 91             {
 92                 buy[p[i]]=have[p[i]]=1;
 93                 while (buy[qin[headin]]) headin++;
 94                 cur_ans=qin[headin];
 95                 if (headout<tailout) cur_ans=min(cur_ans,qout[headout]);
 96             }
 97             else if (have[p[i]])
 98             {
 99                 have[p[i]]=0;
100                 q[tail++]=p[i];
101                 while (headout<tailout && qout[tailout-1]>p[i]) tailout--;
102                 qout[tailout++]=p[i];
103                 cur_ans=min(qin[headin],qout[headout]);
104             }
105             else
106             {
107                 if (head==tail) cur_ans=0;
108                 else
109                 {
110                     have[q[head]]=1;
111                     if (qout[headout]==q[head]) headout++;
112                     head++;
113                     cur_ans=qin[headin];
114                     if (headout<tailout) cur_ans=min(cur_ans,qout[headout]);
115                 }
116             }
117             update_ans(ans_sum,cur_ans,i);
118         }
119         printf("%u\n",ans_sum);
120     }
121     return 0;
122 }
View Code

这题的读入有点新颖。。

posted @ 2017-11-06 06:53  Blue233333  阅读(282)  评论(0编辑  收藏  举报