被以前自己瞎YY的东西坑了T T...单调队列的确是可以维护这种操作的....
显然这题可以转化成维护不在车上的东西的最小值, 支持插入和删去最早出现的值,然后就可以用单调队列了T T
#include#include #include #include #include #define ll long long #define uint unsigned int using namespace std; const int maxn=20000010, inf=1e9; int n, m, a, b, d, T, l, r, L, R, up, fir, firans; int p[maxn], h[maxn], q[maxn]; uint ans_sum, cur_ans; bool fly[maxn], car[maxn]; namespace IO{ int c; unsigned int seed; unsigned int randnum(){ seed^=seed<<13; seed^=seed>>17; seed^=seed<<5; return seed; } inline int read(int &x){scanf("%d",&x);return x;} inline void init_case(int &m,int &a,int &b,int &d,int p[]){ scanf("%d%u%d%d%d%d",&m,&seed,&a,&b,&c,&d); for(int i=1;i<=m;i++){ if(randnum()%c==0) p[i]=-1; else p[i]=randnum()%b; } } inline void update_ans(unsigned int &ans_sum,unsigned int cur_ans,int no){ const static unsigned int mod=998244353; ans_sum^=(long long)no*(no+7)%mod*cur_ans%mod; } } using IO::read; using IO::init_case; using IO::update_ans; inline void qpush(int x) { while(L<=R && q[R]>=x) R--; q[++R]=x; } inline int min(int a, int b){return aa:b;} int main() { read(T); while(T--) { init_case(m, a, b, d, p); up=max(a+1, b); memset(fly, 0, (up+1)); memset(car, 0, (up+1)); L=1; R=0; l=1; r=0; ans_sum=0; firans=a+1; for(int i=0;i<=a;i++) car[i]=1; for(int i=1;i<=m;i++) { cur_ans=0; if(p[i]==-1) { if(l<=r && !d) { if(L<=R && q[L]==h[l]) L++; fly[h[l++]]=0, cur_ans=(L<=R)?min(firans, q[L]):firans; } } else { if(!car[p[i]]) { car[p[i]]=1; while(car[firans]) firans++; cur_ans=(L<=R)?min(firans, q[L]):firans; } else if(car[p[i]] && !fly[p[i]] && !d) fly[p[i]]=1, h[++r]=p[i], qpush(p[i]), cur_ans=(L<=R)?min(firans, q[L]):firans; else if(l<=r && !d) { if(L<=R && q[L]==h[l]) L++; fly[h[l++]]=0, cur_ans=(L<=R)?min(firans, q[L]):firans; } } update_ans(ans_sum, cur_ans, i); } printf("%u\n", ans_sum); } return 0; }