不想翻是哪个题了

因为是选子序列,把序列排序之后和原序列等价。

在第 \(i\) 个位置上存四元组 \([f_i,S_i,g_i,T_i]\) 分别表示以第 \(i\) 个数为结尾的权值和、\(\sum_{j=1}^{i} f_j\)、以第 \(i\) 个数为结尾的方案(即 \(2^{cnt([1,i])-1}\))、\(\sum_{j=1}^{i} g_j a_j\),转移是简单的,于是可以直接 \(\text{DDP}\) 做到 \(O(k^3 n \log n)\)\(k = 4\)\(\log n\) 是线段树给的,算下来过不了(

换种思路,因为是期望,考虑线性性,对每个 pair \((i,j)\)\(i \gt j\))计算它们的贡献,那么当且仅当 \(k \in (j,i)\) 均不被选且 \(i,j\) 均被选,也就是有 \(\dfrac{a_ia_j}{2^{i-j+1}}\) 的贡献,于是有

\[\large{ \sum_{i=1}^{n} \sum_{j=1}^{i-1} \dfrac{a_ia_j}{2^{i-j+1}} = \sum_{i=1}^{n} 2^{-i}a_i \sum_{j=1}^{i-1} 2^{j-1}a_j } \]

权值线段树上维护 \(\begin{aligned} S_1(l,r) = \sum_{i=l}^{r} 2^{-i}a_i \end{aligned}\)\(\begin{aligned} S_2(l,r) = \sum_{i=l}^{r} 2^{i-1}a_i \end{aligned}\)\(\begin{aligned} S(l,r) = \sum_{i=l}^{r} 2^{-i}a_i \sum_{j=l}^{i-1} 2^{j-1}a_j \end{aligned}\),可以轻易地 Push Up

离散化的方法同 掉进兔子洞,即相同数加上已出现次数,使得每个操作的值对应权值线段树上恰好一个叶子。

复杂度 \(O((n + q) \log (n+q))\)

#define Geq(a,n,x) lower_bound(a+1,a+n+1,x)-a
using ll = long long;
constexpr int N = 300003, p = 1e9+7;
inline int P(int &x,int y){ return (x+=y)>=p&&(x-=p), x; }
int n, q, a[N], Pw[N], iPw[N], cnt[N<<1], b[N<<1], len;
struct qry { int x, d; } qr[N]; bitset<N<<1> vis;

__attribute__((constructor)) static void
_sntnt_miao_qie_zhe_ge_ti_tai_qiang_le_() {
	Pw[0] = iPw[0] = 1, Pw[1] = 2, iPw[1] = 500000004;
	for(int i=2;i<N;++i) Pw[i] = (Pw[i-1]<<1)%p, iPw[i] = 1ll*iPw[i-1]*iPw[1]%p;
}

struct SegTree {
	int siz[N<<3], S1[N<<3], S2[N<<3], S[N<<3];
	inline void Push(int u){
		int lc = u<<1, rc = u<<1|1, d1 = 1ll*iPw[siz[lc]]*S1[rc]%p, d2 = 1ll*Pw[siz[lc]]*S2[rc]%p;
		P(S1[u] = S1[lc], d1), P(S2[u] = S2[lc], d2), siz[u] = siz[lc] + siz[rc], P(S[u] = S[lc], S[rc]), P(S[u], 1ll*S2[lc]*d1%p);
	}
	inline void Mdf(int u,int l,int r,int x){
		if(l == r) return vis[l] ? (siz[u] = 1, S1[u] = 1ll*iPw[1]*b[l]%p, S2[u] = b[l]) : (siz[u] = S1[u] = S2[u] = 0), void();
		int mid=l+r>>1; x <= mid ? Mdf(u<<1,l,mid,x) : Mdf(u<<1|1,mid+1,r,x); Push(u);
	}
} T;

main(){
	rd(n); for(int i=1;i<=n;++i) rd(a[i]);
	copy(a+1, a+n+1, b+1), rd(q), len = n;
	for(int i=1;i<=q;++i)
		rd(qr[i].x), b[++len] = rd(qr[i].d);
	sort(b+1, b+len+1);
	auto Discrete = [](int &x)->void { int y = Geq(b, len, x); x = y + cnt[y], ++cnt[y]; };
	for(int i=1;i<=n;++i)
		Discrete(a[i]), vis[a[i]] = 1, T.Mdf(1,1,len,a[i]);
	writeln(T.S[1]); //, T.Prt();
	for(int i=1;i<=q;++i)
		Discrete(qr[i].d), vis[a[qr[i].x]] = 0, T.Mdf(1,1,len,a[qr[i].x]),
		vis[(a[qr[i].x] = qr[i].d)] = 1, T.Mdf(1,1,len,a[qr[i].x]), writeln(T.S[1]); //, T.Prt();
}
posted @ 2023-05-26 00:47  Neutral1sed  阅读(22)  评论(0)    收藏  举报