这是小Z的袜子某一篇题解的AC思路:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int a[50005];
struct query{
int id;
int l, r;
int a, b;
}q[50005];
int s[50005], ans = 0;
inline int gcd(int a, int b) {
return b > 0 ? gcd(b, a % b) : a;
}
inline void update(int p, int add){
ans -= s[a[p]] * s[a[p]];
s[a[p]] += add;
ans += s[a[p]] * s[a[p]];
}
signed main(){
int n, m;
scanf("%lld %lld", &n, &m);
for(int i = 1; i <= n; i++)
scanf("%lld", &a[i]);
int len = sqrt(n);
for(int i = 1; i <= m; i++)
scanf("%lld %lld", &q[i].l, &q[i].r), q[i].id = i;
sort(q + 1, q + m + 1, [len](query A, query B)->bool{
if((A.l - 1) / len + 1 == (B.l - 1) / len + 1)
return A.r < B.r;
return A.l < B.l;
});
for(int i = 1, l = 1, r = 0; i <= m; i++){
for(; r < q[i].r; r++) update(r + 1, 1);
for(; r > q[i].r; r--) update(r, -1);
for(; l < q[i].l; l++) update(l, -1);
for(; l > q[i].l; l--) update(l - 1, 1);
if(q[i].l == q[i].r){
q[i].a = 0, q[i].b = 1;
continue;
}
q[i].a = ans - (q[i].r - q[i].l + 1);
q[i].b = (q[i].r - q[i].l + 1) * (q[i].r - q[i].l);
int g = gcd(q[i].a, q[i].b);
q[i].a /= g, q[i].b /= g;
}
sort(q + 1, q + m + 1, [](query A, query B)->bool{
return A.id < B.id;
});
for(int i = 1; i <= m; i++)
printf("%lld/%lld\n", q[i].a, q[i].b);
return 0;
}
我疑惑的是,为什么凭借几条update
就可以求出区间平方和呢?有大佬可以给出直观一点的过程吗?