CCPC2024-Zhengzhou G Same Sum(线段树)
给一个序列。两种操作:
-
区间加;
-
查询一个偶数长区间,其中的值是否可以两两配对得到和相等。
首先知道区间内的值两两配对得到的相等的和值为区间的平均数 m 。
可以转化为,这个区间的值分布关于 m 对称。
\[x^{a_i+a_j}=x^{2m} \Rightarrow x^{a_i}=\frac{x^{2m}}{x^{a_j}}, x^{a_j}=\frac{x^{2m}}{x^{a_i}}
\]
\[\sum_{i=l}^r x^{a_i}=x^{2m}\sum_{i=l}^r x^{-a_i}
\]
维护区间平均值 m,\(\sum x^{a_i}\),\(\sum x^{-a_i}\) 即可。
这个值为什么能正确刻画这个分布?我还没搞明白...QvQ?
const i64 x=(rng()%P*rng()%P)%P;
i64 ux; // ux=power(x,P-2);
i64 power(i64 A,i64 B)
{
u64 ANS=1,BASE=A%P;
for (;B;B>>=1,BASE=BASE*BASE%P)
if (B&1) ANS=ANS*BASE%P;
return ANS;
}
void R()
{
int n,q;
cin>>n>>q;
vector<i64> a(n);
for (int i=0;i<n;i++) cin>>a[i];
vector<Info> info(n);
for (int i=0;i<n;i++)
info[i]={power(x,a[i]),power(ux,a[i]),a[i],i,i};
SGT<Info,Tag> sgt(info);
while (q--)
{
int opt,l,r;
i64 v;
cin>>opt>>l>>r; l--;
if (opt==1)
{
cin>>v;
sgt.rangeApply(l,r,{power(x,v),power(ux,v),v});
}
else
{
auto [U,V,m,ll,rr]=sgt.rangeQuery(l,r);
i64 len=r-l;
if (m%(len/2)!=0) { cout<<"NO\n"; continue; }
if (V*power(x,m/(len/2))%P==U) cout<<"YES\n";
else cout<<"NO\n";
}
}
return;
}

浙公网安备 33010602011771号