Analysis:

In fact, I have said so much in the title. There is a sentence

The same number can only be inserted c times at most. C=10

That is to say, we can approximate this sequence as random.

So think straight ahead. We found another condition:

Ensure that sequence A is not empty at any time, and the elements in sequence A are not equal to each other

We can directly tell where each number of records can appear, and the answer size is directly reduced to the logloglog level.

Note that dp[i]dp[i]dp[i] represents the longest length of the sequence starting with iii, cnt[i][j]cnt[i][j]cnt[i][j] represents the number starting with iii, and the length of the sequence is the number of jjj.

Then four operations can be done directly:

Push "front: directly enumerate multiple to find all multiple update answers.

Pop "front: directly delete the value of the sequence header and dpdpdp value.

Push back: preprocess factor table, enumerate all factors and update all answers before.

pop_back: preprocess factor table, enumerate all factors and update all previous answers.

Code:

```#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const

namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
}

inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;

using std::cout;
using std::cerr;

cs int P=1e6+6;

std::vector<int> factor,pre;
int prime[P],pcnt,last[P];
bool mark[P];

inline void _copy(int goal,int f,int p){
bool flag=false;
for(int re i=last[f];~i;i=pre[i]){
int v=factor[i];
if(f%(v*p)){
if(flag)pre.emplace_back(factor.size()-1);
else pre.emplace_back(last[f]),flag=true;
factor.emplace_back(v*p);
}
}
last[goal]=factor.size()-1;
}

inline void linear_sieves(int len=P-6){
factor.emplace_back(1);
pre.emplace_back(-1);
last[1]=0;
for(int re i=2;i<=len;++i){
if(!mark[i])prime[++pcnt]=i,_copy(i,1,i);
for(int re j=1;i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
_copy(i*prime[j],i,prime[j]);
if(i%prime[j]==0)break;
}
}
}

int n,m,q;
int l,r;
cs int B=21;
int ans[B];
void query(){for(int re i=B-1;i;--i)if(ans[i])return (void)(cout<<i<<" "<<ans[i]<<"\n");assert(false);}

int pos[P],a[P],cnt[P][B];
int dp[P];
inline void clear(int x){
memset(cnt[x],0,sizeof cnt[x]);
dp[x]=1,cnt[x][1]=1;
}

inline void push_front(int x){
clear(x);
a[pos[x]=--l]=x;
for(int re i=x+x;i<=m;i+=x)if(pos[i])++cnt[x][dp[i]+1];
for(int re i=B-1;i;--i)if(cnt[x][i]){dp[x]=i;break;}
++ans[dp[x]];
}
inline void pop_front(){
int x=a[l++];
pos[x]=0;
--ans[dp[x]];
}

inline void update(int x,int val,int delta){
ans[val]+=delta;
for(int re i=last[x];~i;i=pre[i]){
int v=factor[i];
if(pos[v]<pos[x])cnt[v][val+1]+=delta;
}
}

int val[P],old[P],tot;
inline void push_back(int x){
clear(x);
a[pos[x]=++r]=x;
tot=0;
for(int re i=last[x];~i;i=pre[i]){
int v=factor[i];
if(pos[v]){
val[++tot]=v;
old[v]=dp[v];
}
}
std::sort(val+1,val+tot+1);
update(x,dp[x],1);
for(int re j=tot-1;j;--j){
int v=val[j];
for(int re i=B-1;i;--i)
if(cnt[v][i]){
dp[v]=i;
break;
}
if(old[v]==dp[v])continue;
update(v,old[v],-1);
update(v,dp[v],1);
}
}

inline void pop_back(){
int x=a[r--];
tot=0;
for(int re i=last[x];~i;i=pre[i]){
int v=factor[i];
if(pos[v]){
val[++tot]=v;
old[v]=dp[v];
}
}
std::sort(val+1,val+tot+1);
update(x,dp[x],-1);
for(int re j=tot-1;j;--j){
int v=val[j];
for(int re i=B-1;~i;--i)
if(cnt[v][i]){
dp[v]=i;
break;
}
if(old[v]==dp[v])continue;
update(v,old[v],-1);
update(v,dp[v],1);
}
pos[x]=0;
}

signed main(){
std::ios::sync_with_stdio(false);
n=getint(),m=getint(),q=getint();
linear_sieves(m);
l=5e5,r=l-1;
while(n--)push_back(getint());
while(query(),q--)switch(getint()){
case 0:push_front(getint());break;
case 1:push_back(getint());break;
case 2:pop_front();break;
case 3:pop_back();break;
}
return 0;
}
```

Tags: iOS

Posted on Wed, 04 Dec 2019 13:01:05 -0500 by ShadowX