对于询问,我们可以分两种情况讨论:
1.第x株植物不变种且排名不变,当且仅当对于所有的ai<ax且kai>=ax的植物不变种,设这样的植物有p株
2.第x株植物变种且排名不变,当且仅当对于所有的ax<=ai<kax的植物变种,设这样的植物有q株
则x排名不变的概率为(1-pr)^(p+1)+pr^(q+1),用数据结构维护即可,这里使用的是线段树
#include<cstdio> #include<algorithm> using namespace std; const int N=200005; const long long mod=998244353; int n,m,pr,k,left,right,a[N],tree[N<<2],t[N*2],len,op[N],x[N],y[N]; long long ans,p[N],np[N]; void modify(int k,int l,int r,int x,int v){ if (l==r){ tree[k]+=v; return ; } int mid=l+r>>1; if (x<=mid) modify(k<<1,l,mid,x,v); else modify(k<<1|1,mid+1,r,x,v); tree[k]=tree[k<<1]+tree[k<<1|1]; } int query(int k,int l,int r,int x,int y){ if (x<=l&&r<=y){ return tree[k]; } int mid=l+r>>1,s=0; if (x<=mid) s+=query(k<<1,l,mid,x,y); if (mid<y) s+=query(k<<1|1,mid+1,r,x,y); return s; } int main(){ freopen ("lycoris.in","r",stdin); freopen ("lycoris.out","w",stdout); scanf ("%d%d%d%d",&n,&m,&pr,&k); p[0]=np[0]=1; for (register int i=1;i<=n;++i){ p[i]=1ll*p[i-1]*pr%mod; np[i]=1ll*np[i-1]*(1-pr)%mod; } for (register int i=1;i<=n;++i){ scanf ("%d",&a[i]); t[++len]=a[i]; } for (register int i=1;i<=m;++i){ scanf ("%d%d",&op[i],&x[i]); if (op[i]==1){ scanf ("%d",&y[i]); t[++len]=y[i]; } } sort (t+1,t+1+len); len=unique(t+1,t+1+len)-t-1; for (register int i=1;i<=n;++i){ modify(1,1,len,lower_bound(t+1,t+1+len,a[i])-t,1); } for (register int i=1;i<=m;++i){ if (op[i]==1){ modify(1,1,len,lower_bound(t+1,t+1+len,a[x[i]])-t,-1); a[x[i]]=y[i]; modify(1,1,len,lower_bound(t+1,t+1+len,a[x[i]])-t,1); } else{ ans=0ll; right=lower_bound(t+1,t+1+len,a[x[i]])-t-1; left=lower_bound(t+1,t+1+len,(a[x[i]]-1)/k+1)-t; if (left<=right) ans=np[query(1,1,len,left,right)]; else ans=1; ans=ans*(1-pr)%mod; left=lower_bound(t+1,t+1+len,a[x[i]])-t; right=lower_bound(t+1,t+1+len,a[x[i]]*k)-t-1; if (t[len]<a[x[i]]*k) right=len; int num=0; if (left<=right) num=query(1,1,len,left,right)-1; ans=(ans+pr*p[num])%mod; printf ("%lld\n",(ans+mod)%mod); } } return 0; }