定义一个 (n) 元序列 (p_i),如果 (n=1),则序列权值为 (0),否则序列权值就是原序列排序后相邻两项乘积的和。现在等概率地选出一个子序列,问它的权值的期望是多少。支持动态单点修改。
Solution
对于静态情况,答案为
[sum_{i=1}^n sum_{j=i+1}^n frac{p_i p_j}{2^{j-i+1}}
]
考虑用线段树维护,对于区间 ([l,r]),我们设 (val) 为当前区间权值,(lv=sum_{i=l}^r p_i2^{i-l}),(rv=sum_{i=l}^r p_i/2^{i-l+1}),(sz) 是当前区间内数的个数,则
[val=val_L+val_R+frac{1}{2} vl_Lvr_R/2^{sz_L} \
sz=sz_L+sz_R \
vl=vl_L+vl_R2^{sz_L} \
vr=vr_L+vr_R/2^{sz_L}
]
对于单点 (a),它的 (val=0, sz=1, vl=a, vr=a/2)
考虑到序列中有重复元素,我们先将所有元素(包括修改的)一起读进来排序,然后将原始的先激活,修改后的先不激活((val=0,sz=0,vl=0,vr=0)),一起挂在线段树上
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1000005;
const int mod =1e+9+7;
const int dbg = 0;
struct item {
int v,x,t;
bool operator < (const item &b) {
return v < b.v;
}
} I[N];
int n,m,seq[N],src[N],m1[N],m2[N],pos[N],p[N],iqp[N],qp[N];
int qpow(int p,int q) {
return (q&1?p:1)*(q?qpow(p*p%mod,q/2):1)%mod;
}
int inv(int p) {
return qpow(p,mod-2);
}
struct node {
int val,sz,vl,vr;
} a[N*3];
node merge(node l,node r) {
node ret;
ret.val=(l.val+r.val+l.vl*r.vr%mod*iqp[l.sz]%mod)%mod;
ret.sz=l.sz+r.sz;
ret.vl=(l.vl+r.vl*qp[l.sz])%mod;
ret.vr=(l.vr+r.vr*iqp[l.sz])%mod;
return ret;
}
void open(int p,int l,int r,int x) {
if(l==r) {
a[p]={0,1,I[x].v,I[x].v*inv(2)%mod};
}
else {
if(x<=(l+r)/2) open(p*2,l,(l+r)/2,x);
else open(p*2+1,(l+r)/2+1,r,x);
a[p]=merge(a[p*2],a[p*2+1]);
}
}
void open(int x) {
if(dbg) cout<<"open "<<x<<endl;
open(1,1,n+m,x);
}
void close(int p,int l,int r,int x) {
if(l==r) {
a[p]={0,0,0,0};
}
else {
if(x<=(l+r)/2) close(p*2,l,(l+r)/2,x);
else close(p*2+1,(l+r)/2+1,r,x);
a[p]=merge(a[p*2],a[p*2+1]);
}
}
void close(int x) {
if(dbg) cout<<"close "<<x<<endl;
close(1,1,n+m,x);
}
signed main() {
ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<=1e6;i++) {
iqp[i]=inv(qpow(2,i));
qp[i]=qpow(2,i);
}
for(int i=1;i<=n;i++) {
cin>>p[i];
I[i].v=p[i];
I[i].x=i;
I[i].t=0;
}
cin>>m;
for(int i=1;i<=m;i++) {
int t1,t2;
cin>>t1>>t2;
m1[i]=t1;
m2[i]=t2;
I[n+i].v=t2;
I[n+i].x=i;
I[n+i].t=1;
}
sort(I+1,I+n+m+1);
for(int i=1;i<=n+m;i++) {
src[i]=I[i].v;
if(I[i].t==0) {
seq[I[i].x]=i;
}
else {
pos[I[i].x]=i;
}
}
for(int i=1;i<=n;i++) {
open(seq[i]);
}
cout<<a[1].val<<endl;
for(int i=1;i<=m;i++) {
close(seq[m1[i]]);
open(pos[i]);
seq[m1[i]]=pos[i];
cout<<a[1].val<<endl;
}
}