1. 程式人生 > >「LibreOJ NOIP Round #1」七曜聖賢

「LibreOJ NOIP Round #1」七曜聖賢

題目囉嗦:
支援三個操作:

不可重複集合:
1.加入一個數

2.刪除一個數

3.恢復目前最早的一次刪除的數

操作可能不合法,每次有效操作之後求集合的mex(最小沒有出現過的數)

 

50組資料+1e6,必須O(N)

 

維護刪除、恢復的數的操作可以佇列維護。

數有沒有在集合裡可以全域性bool陣列記錄

 

加入刪除一個數,mex怎麼維護?

考慮化簡問題:
只插入?

直接mex往上走到第一個沒有出現的數即可。單增,O(N)

有刪除?

如果刪除小的一個數,mex要跳下來,然後再恢復這個刪除的數,mex又得一步一步走上去。

能不能不跳?

可以!

只要知道當前刪除的數最小的一個,和mex取min即可。

維護刪除的數的集合:

插入一個數,刪除一個數,維護最小的數。怎麼看也得帶logn

但是,發現恢復數是按照時間順序從小到大

所以一個數如果比後面的數大,那麼直到這個刪除的數被恢復也不可能成為最小值。

單調佇列維護。

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^'0')
using namespace std;
typedef long long ll;
il void rd(int &x){
    
char ch;x=0;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=1e6+5; const int mod=998244353; int ans[N]; int q[2*N],l,r; queue<int>que; int p[N]; bool on[2
*N],has[2*N]; 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; void clear(){ memset(on,0,sizeof on); memset(q,0,sizeof q); l=1,r=0; memset(has,0,sizeof has); while(!que.empty()) que.pop(); } int get(){ while(l<=r&&on[q[l]]) ++l; if(l<=r) return q[l]; return 0x3f3f3f3f; } void upda(int c){ while(l<=r&&q[r]>=c) --r; q[++r]=c; } int main(){ int T;read(T); int m,a,b,d; while(T--){ clear(); init_case(m,a,b,d,p); for(reg i=0;i<=a;++i) on[i]=1,has[i]=1; int mex=a+1; for(reg i=1;i<=m;++i){ int k; if(p[i]==-1){//case 3 if(que.empty()||d){ ans[i]=0;goto end; }else{ k=que.front();que.pop(); on[k]=1; } }else{ if(!on[p[i]]&&!has[p[i]]){ has[p[i]]=1; on[p[i]]=1; }else if(on[p[i]]){ if(d==1){ ans[i]=0;goto end; }else{ que.push(p[i]); on[p[i]]=0; upda(p[i]); } }else{ if(que.empty()||d){ ans[i]=0;goto end; }else{ k=que.front();que.pop(); on[k]=1; } } } while(on[mex]) ++mex; ans[i]=min(mex,get()); end:; } ll op=0; for(reg i=1;i<=m;++i){ op^=(ll)ans[i]*((ll)i*i%mod+7*i%mod)%mod; } printf("%lld\n",op); } return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2018/12/31 16:28:17 */