定义差后序列为一个数据结构,支持两种操作:
0 x
:插入一个数 x x x1
:随机删除一个不是最大值的数,如果只有一个数则删除该数有 n n n次操作。
对于每次插入,求这个数期望被删除的时间(如果到最后也没被删除则删除时间为 0 0 0);对于每次删除,求删除的数的期望值。
输出答案对 998244353 998244353 998244353取模后的值。
1 ≤ n ≤ 1 0 6 , 0 < x < 998244353 1\leq n\leq 10^6,0
首先,我们发现,不是最大值的数是等价的。
会有删空的情况,那我们就对每一段单独处理。
我们先考虑每次插入时的询问。设 n w i nw_i nwi表示在第 i − 1 i-1 i−1次操作后的不是最大值的数的期望被删除的时间,设第 i − 1 i-1 i−1次操作后当前队列中不是最大值的数有 k k k个,则
n w i = 1 k + k − 1 k × n w i − 1 nw_i=\dfrac 1k+\dfrac{k-1}{k}\times nw_{i-1} nwi=k1+kk−1×nwi−1
对于每个插入的数,找到后面第一个比它大的数的插入时间 t t t,则 n w t nw_t nwt即为当前插入操作的答案。
再考虑删除操作。我们设 s u m sum sum表示当前队列中不是最大值的数的期望和,设 m x mx mx为当前的最大值。对于每次插入,判断当前插入的数 k k k是否大于 m x mx mx。如果大于 m x mx mx,则将原来的最大值加到 s u m sum sum中,并将 k k k设为新的最大值;否则将 k k k加到 s u m sum sum中。对于每次删除,删除的数的期望值为 s u m k \frac{sum}{k} ksum,删除后队列中不是最大值的数的期望和为 k − 1 k ⋅ s u m \frac{k-1}{k}\cdot sum kk−1⋅sum,令 s u m = k − 1 k ⋅ s u m sum=\frac{k-1}{k}\cdot sum sum=kk−1⋅sum即可。
时间复杂度为 O ( n ) O(n) O(n)。
#include
using namespace std;
const int N=1000000;
const long long mod=998244353;
int n,mx,hv[N+5],nxt[N+5],ed[N+5];
long long sum=0,jc[N+5],ny[N+5],nw[N+5],ans[N+5];
struct node{
int tp,x;
}w[N+5];
long long mi(long long t,long long v){
if(!v) return 1;
long long re=mi(t,v/2);
re=re*re%mod;
if(v&1) re=re*t%mod;
return re;
}
void init(){
jc[0]=1;
for(int i=1;i<=N;i++) jc[i]=jc[i-1]*i%mod;
ny[N]=mi(jc[N],mod-2);
for(int i=N-1;i>=0;i--) ny[i]=ny[i+1]*(i+1)%mod;
}
int main()
{
freopen("queue.in","r",stdin);
freopen("queue.out","w",stdout);
init();
scanf("%d",&n);
for(int i=1;i<=n;i++){
hv[i]=hv[i-1];
scanf("%d",&w[i].tp);
if(w[i].tp==0){
scanf("%d",&w[i].x);
++hv[i];
if(w[i].x>w[mx].x){
nxt[mx]=i;mx=i;
}
else nxt[i]=i;
}
else{
--hv[i];
if(!hv[i]){
ed[mx]=i;
nxt[mx]=i;mx=0;
}
}
}
for(int i=n;i>=1;i--){
if(w[i].tp==0){
nw[i]=nw[i+1];
if(w[nxt[i]].tp!=1) ed[i]=nw[nxt[i]];
}
else{
if(!hv[i]) nw[i]=0;
else{
long long nyt=ny[hv[i]]*jc[hv[i]-1]%mod;
nw[i]=(1ll*i*nyt%mod+nyt*(hv[i]-1)%mod*nw[i+1]%mod)%mod;
}
}
}
mx=0;
for(int i=1;i<=n;i++){
if(w[i].tp==0){
if(w[i].x>w[mx].x){
sum=(sum+w[mx].x)%mod;mx=i;
}
else sum=(sum+w[i].x)%mod;
}
else{
if(!hv[i]){
ans[i]=w[mx].x;
sum=0;mx=0;
}
else{
long long nyt=ny[hv[i]]*jc[hv[i]-1]%mod;
ans[i]=sum*nyt%mod;
sum=nyt*(hv[i]-1)%mod*sum%mod;
}
}
}
for(int i=1;i<=n;i++){
if(w[i].tp==0) printf("%d ",ed[i]);
else printf("%lld ",ans[i]);
}
return 0;
}