CF1316F Battalion Strength

\(CF1316F Battalion Strength\)

话说这题真的能评黑吗

Solution

先考虑暴力。

将数组排序。我们枚举 \(p_i,p_j(i<j)\) 为子序列中相邻的两个数,那么显然成立的概率为 \(\frac{1}{2^{j-i+1}}\) ,那么它们对答案的贡献就是 \(p_i\cdot p_j\cdot \frac{1}{2^{j-i+1}}\)

所以答案为:

\[\sum_{j=2}^n\sum_{i=1}^{j-1}p_i\cdot p_j\cdot \frac{1}{2^{j-i+1}} \]

时间复杂度为 \(O(n^2)\)

我们将式子拆分一下:

\[\sum_{j=2}^n p_j\cdot \frac{1}{2^{j+1}} \sum_{i=1}^{j-1} p_i\cdot 2^i \]

后面关于 \(i\) 的部分,可以使用前缀和解决,时间复杂度变为 \(O(n)\)

但是本题带修,所以总复杂度为 \(O(n^2)\)

考虑使用权值线段树处理修改。

我们知道 \(p_i,p_j\) 的答案为 \((p_i\cdot 2^i)\times (p_j\cdot \frac{1}{2^{j+1}})\) ,那么我们分别维护出区间这两个数的和即可计算答案。

线段树中纪录 \(4\) 个变量 \(pre,suf,sum,sz\) ,分别表示 \(\sum p_i\cdot \frac{1}{2^{i+1}}\)\(\sum p_i\cdot 2^i\) 、答案以及数的个数。

每次合并考虑左边对右边的贡献。

由于有相同的数,我们删除和添加不好处理,我们将相同的数拆成几个不同的区间即可。

Code

#include<bits/stdc++.h>
#define del(a,i) memset(a,i,sizeof(a))
#define ll long long
#define inl inline
#define il inl void
#define it inl int
#define ill inl ll
#define re register
#define ri re int
#define rl re ll
#define mid ((l+r)>>1)
#define lowbit(x) (x&(-x))
#define INF 0x3f3f3f3f
using namespace std;
template<class T>il read(T &x){
	int f=1;char k=getchar();x=0;
	for(;k>'9'||k<'0';k=getchar()) if(k=='-') f=-1;
	for(;k>='0'&&k<='9';k=getchar()) x=x*10+k-'0';
	x*=f;
}
template<class T>il _print(T x){
	if(x>=10) _print(x/10);
	putchar(x%10+'0');
}
template<class T>il print(T x){
	if(x<0) putchar('-'),x=-x;
	_print(x);
}
ll mul(ll a,ll b,ll mod){long double c=1.;return (a*b-(ll)(c*a*b/mod)*mod)%mod;}
it qpow(int x,int k,int mod){
	int res=1,bas=x;
	while(k){
		if(k&1) res=1ll*res*bas%mod;
		bas=1ll*bas*bas%mod,k>>=1;
	}
	return res;
}
const int N = 3e5+5,mod = 1e9+7;
it add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
it mul(int x,int y){return 1ll*x*y%mod;}
il inc(int &x,int y){x=add(x,y);}
int n,m,p,k,val[N],bas[N],inv[N],pre[N],pos[N<<1];
struct Node{
	int ty,val,pos;
}node[N<<1];
inl bool cmp1(Node x,Node y){return x.val<y.val;}
inl bool cmp2(Node x,Node y){return x.ty<y.ty;}
struct Seg_Tree{
	int pre,suf,sum,sz;
}T[N<<3];
#define lc (cur<<1)
#define rc (cur<<1|1)
il pushup(int cur){
	T[cur].sz=T[lc].sz+T[rc].sz;
	T[cur].pre=add(T[lc].pre,mul(T[rc].pre,bas[T[lc].sz]));
	T[cur].suf=add(T[lc].suf,mul(T[rc].suf,inv[T[lc].sz]));
	T[cur].sum=add(add(T[lc].sum,T[rc].sum),mul(mul(T[lc].pre,T[rc].suf),inv[T[lc].sz]));
}
il Updata(int cur,int l,int r,int pos,int s1,int s2){
	if(l==r){
		T[cur].pre=s1,T[cur].suf=s2,T[cur].sz=1,T[cur].sum=0;
		return ;
	}
	if(mid>=pos) Updata(lc,l,mid,pos,s1,s2);
	else Updata(rc,mid+1,r,pos,s1,s2);
	pushup(cur);
}
il Delete(int cur,int l,int r,int pos){
	if(l==r){
		T[cur].pre=T[cur].suf=T[cur].sum,T[cur].sz=0;
		return ;
	}
	if(mid>=pos) Delete(lc,l,mid,pos);
	else Delete(rc,mid+1,r,pos);
	pushup(cur);
}
int main(){
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	read(n),bas[0]=1;
	for(ri i=1;i<=n;++i) bas[i]=mul(bas[i-1],2);
	for(ri i=1;i<=n;++i) read(val[i]),node[i]=(Node){i,val[i],0};
	read(m),inv[n]=qpow(bas[n],mod-2,mod);
	for(ri i=n-1;i>=0;--i) inv[i]=mul(inv[i+1],2);
	for(ri i=1;i<=m;++i){
		read(p),read(k);
		node[i+n]=(Node){n+i,k,p};
	}
	sort(node+1,node+1+n+m,cmp1);
	for(ri i=1;i<=n+m;++i) pos[node[i].ty]=i;
	sort(node+1,node+1+n+m,cmp2);
	for(ri i=1;i<=n;++i) Updata(1,1,n+m,pos[i],mul(val[i],2),mul(val[i],inv[2])),pre[i]=pos[i];
	printf("%d\n",T[1].sum);
	for(ri i=1;i<=m;++i){
		p=node[i+n].pos,k=node[i+n].val;
		Delete(1,1,n+m,pre[p]);
		Updata(1,1,n+m,pos[i+n],mul(k,2),mul(k,inv[2])),pre[p]=pos[i+n];
		printf("%d\n",T[1].sum);
	}
	return 0;
}
posted @ 2020-03-28 10:12  TheShadow  阅读(166)  评论(0编辑  收藏  举报