小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;
}
}

浙公网安备 33010602011771号