CF86D Powerful array
题面翻译
- 给定长度为 \(n\) 的序列 \(a\),有 \(q\) 次询问,每次询问给出两个数 \(l,r\)。
- 对于每次询问,设 \(cnt_i\) 表示 \(i\) 在 \(a_l,a_{l+1},\cdots,a_r\) 出现的次数,您需要求出 \(\displaystyle\sum_i cnt_i^2\cdot i\)。
- \(1\le n,q\le 2\times 10^5\),\(1\le a_i\le 10^6\),\(1\le l\le r\le n\)。
样例 #1
样例输入 #1
3 2
1 2 1
1 2
1 3
样例输出 #1
3
6
样例 #2
样例输入 #2
8 3
1 1 2 2 1 3 1 1
2 7
1 6
2 7
样例输出 #2
20
20
20
分析
发现已知当前区间 \([l,r]\) 可以转移到区间 \([l-1,r],[l+1,r],[l,r-1],[l,r+1]\),再维护一个区间出现次数的信息即可莫队。
#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+(c&15),c=getchar();
return x*f;
}
int n,m,bl,a[200005],cnt[1000005],pos[200005],ans[200005],res;
struct node{
int l,r,id;
}q[200005];
bool cmp(node x,node y){return pos[x.l]^pos[y.l]?pos[x.l]<pos[y.l]:x.r<y.r;}
void add(int x){
res-=cnt[a[x]]*cnt[a[x]]*a[x];
++cnt[a[x]];
res+=cnt[a[x]]*cnt[a[x]]*a[x];
}
void del(int x){
res-=cnt[a[x]]*cnt[a[x]]*a[x];
--cnt[a[x]];
res+=cnt[a[x]]*cnt[a[x]]*a[x];
}
signed main(){
n=read(),m=read();bl=pow(n,0.55);
for(int i=1;i<=n;i++)a[i]=read(),pos[i]=(i-1)/bl+1;
for(int i=1;i<=m;i++)q[i].l=read(),q[i].r=read(),q[i].id=i;
sort(q+1,q+m+1,cmp);
for(int i=1,l=1,r=0;i<=m;i++){
while(q[i].l<l)add(--l);
while(q[i].l>l)del(l++);
while(q[i].r>r)add(++r);
while(q[i].r<r)del(r--);
ans[q[i].id]=res;
}
for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);
return 0;
}

浙公网安备 33010602011771号