[Ynoi2015] 盼君勿忘 题解

CSP 前学习珂学,祝自己 \(while(1)\ rp++\)


考虑求解出每种数对答案的贡献。

\(t=r-l+1,k_x=\sum\limits_{i=l}^r [a_i=x]\),由容斥得贡献为 \(x(2^t-2^{t-k_x})\)

求解 \(k_x\),考虑莫队,时间复杂度为 \(O(n\sqrt n)\),这也是本题的复杂度上限。

由于 \(p\) 会变,所以不能用莫对维护 \(2^i\)。我们希望答案的计算次数级别为 \(O(\sqrt n)\),考虑根号分治:

  • 对于出现次数 \(\le \sqrt n\) 的数,我们用数组 \(num_i\) 统计,表示当前子串出现次数为 \(i\) 的数之和为多少。可以表示为: \(num_i=\sum\limits_{j=1}^{10^5}[k_j=i]\times j\),时间复杂度 \(O(\sqrt n)\)

  • 对于出现次数 \(>\sqrt n\) 的数,我们直接维护它们的 \(k_i\)。由于这种数的个数级别为 \(O(\sqrt n)\),所以也没问题。

现在只需要考虑快速幂的问题。普通快速幂肯定是不行了,时间复杂度会多一只 \(\log\)。考虑预处理可以给到 \(O(\sqrt n)\),选择光速幂。

时间复杂度 \(O(\sqrt n)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5;
int n,m,kl,a[N],l=1,r,ans[N];
struct que{int l,r,p,id;}q[N];
int cmp(que x,que y){
	if(x.l/kl!=y.l/kl)
		return x.l/kl<y.l/kl;
	if(x.l/kl%2) return x.r>y.r;
	return x.r<y.r;
}int pw1[N],pw2[N],p;
void init(int c){
	p=c,pw1[0]=pw2[0]=1;
	for(int i=1;i<=kl;i++)
		pw1[i]=pw1[i-1]*2%p;
	for(int i=1;i<=kl;i++)
		pw2[i]=pw2[i-1]*pw1[kl]%p;
}int kpow(int y){
	return pw1[y%kl]*pw2[y/kl]%p;
}int num[N],sum[N],vis[N],b[N],id;
void add(int x){
	sum[x]++;
	if(vis[x]) return;
	num[sum[x]-1]-=x;
	num[sum[x]]+=x;
}void del(int x){
	sum[x]--;
	if(vis[x]) return;
	num[sum[x]+1]-=x;
	num[sum[x]]+=x;
}signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0),cout.tie(0);
	cin>>n>>m,kl=sqrt(n)+1;
	for(int i=1;i<=n;i++)
		cin>>a[i],num[a[i]]++;
	for(int i=1;i<=1e5;i++){
		if(num[i]>kl)
			b[++id]=i,vis[i]=1;
		num[i]=0;
	}for(int i=1;i<=m;i++)
		cin>>q[i].l>>q[i].r>>q[i].p,q[i].id=i;
	sort(q+1,q+m+1,cmp);
	for(int i=1;i<=m;i++){
		init(q[i].p);int ij=q[i].id;
		while(r<q[i].r) add(a[++r]);
		while(r>q[i].r) del(a[r--]);
		while(l>q[i].l) add(a[--l]);
		while(l<q[i].l) del(a[l++]);
		for(int j=1;j<=id;j++)
			ans[ij]=(ans[ij]+b[j]*(kpow(r-l+1)-kpow(r-l+1-sum[b[j]])))%p;
		for(int j=1;j<=kl;j++)
			ans[ij]=(ans[ij]+num[j]*(kpow(r-l+1)-kpow(r-l+1-j)))%p;
		ans[ij]=(ans[ij]+p)%p;
	}for(int i=1;i<=m;i++)
		cout<<ans[i]<<"\n";
	return 0;
}
posted @ 2024-10-25 23:01  长安一片月_22  阅读(2)  评论(0编辑  收藏  举报