小B的询问

题目链接:https://www.luogu.com.cn/problem/P2709

题意:

给定一个序列,m次查询,每次查询要求返回区间 每个数的出现次数 的平方 之和

思路:

莫队,即将原序列分成n块sqrt(n)的块,再将查询按照l在块的编号为第一关键字,r为第二关键字进行排序
离线双指针进行计算

int n;
int a[maxn];
struct node{
	int l,r,id;
};
bool cmp(node a,node b){
	int k=sqrt(n);
	int x1=a.l/k,x2=b.l/k;
	if(x1!=x2)return x1<x2;
	return a.r<b.r;
}

int cnt[maxn];
int res;

void add(int index){
	cnt[a[index]]++;
	if(cnt[a[index]]!=1)res+=cnt[a[index]]*cnt[a[index]]-(cnt[a[index]]-1)*(cnt[a[index]]-1);
	else res+=1;
//	cout<<"plus "<<endl;
//	debug(res);
}

void del(int index){
	int st=cnt[a[index]],ed=cnt[a[index]]-1;
	cnt[a[index]]--;
	if(ed)res-=(st*st-ed*ed);
	else res-=st*st;
}

void solve(){
	int m,k;cin>>n>>m>>k;
	rep(i,1,n)cin>>a[i];
	vector<node>q;	
	rep(i,1,m){
		int l,r;cin>>l>>r;
		q.pb((node){l,r,i});
	}
	sort(q.begin(),q.end(),cmp);
	vector<int>ans(maxn);
	res=0;
	for(int i=0,l=1,r=0;i<m;i++){
		
		while(l>q[i].l)add(--l);
		while(r<q[i].r)add(++r);
		while(l<q[i].l)del(l++);
		while(r>q[i].r)del(r--);
		ans[q[i].id]=res;
//		debug(res);
	}
	
	rep(i,1,m){
		cout<<ans[i]<<endl;
	}
}
posted @ 2025-04-04 17:29  Marinaco  阅读(18)  评论(0)    收藏  举报
//雪花飘落效果