有一辆车一开始装了编号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 ",ans_sum); 120 } 121 return 0; 122 }
这题的读入有点新颖。。