題目鏈接:https://www.luogu.org/problemnew/show/P1494
離線莫隊
[L,R]區間內:
設每種襪子的數量分別爲:
則答案爲:
化簡即爲:
所以我們求:即可
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cmath>
#define rep(i, s, e) for(int i = s; i < e; ++i)
#define P pair<int, int>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
static const int MAX_N = 5e4 + 5;
static const ll Mod = 1e9 + 7;
struct Query{
int l, r, id, pos;
bool operator < (Query &q)const{
if(pos == q.pos) return r < q.r;
return pos < q.pos;
}
}q[MAX_N];
struct Answer{
ll rev1, rev2;
}rev[MAX_N];
int cnt[MAX_N], a[MAX_N];
ll gcd(ll x, ll y){
return y == 0 ? x : gcd(y, x % y);
}
ll ans; //這裏會卡個long long
void update(int p, int v){
ans -= cnt[a[p]] * cnt[a[p]];
cnt[a[p]] += v;
ans += cnt[a[p]] * cnt[a[p]];
}
void solve(){
int n, m;
scanf("%d%d", &n, &m);
int block = (int)sqrt(n);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for(int i = 1; i <= m; ++i){
scanf("%d%d", &q[i].l, &q[i].r);
q[i].id = i;
q[i].pos = (q[i].l - 1) / block + 1;
}
sort(q + 1, q + m + 1);
int l = 1, r = 0;
for(int i = 1; i <= m; ++i){
if(q[i].l == q[i].r){
rev[q[i].id].rev1 = 0;
rev[q[i].id].rev2 = 1;
continue;
}
while(l < q[i].l) update(l++, -1);
while(l > q[i].l) update(--l, 1);
while(r < q[i].r) update(++r, 1);
while(r > q[i].r) update(r--, -1);
int le = q[i].r - q[i].l + 1;
rev[q[i].id].rev1 = ans - le;
rev[q[i].id].rev2 = (ll)le * (le - 1);
ll gc = gcd(rev[q[i].id].rev1, rev[q[i].id].rev2);
rev[q[i].id].rev1 /= gc;
rev[q[i].id].rev2 /= gc;
}
for(int i = 1; i <= m; ++i) printf("%lld/%lld\n", rev[i].rev1, rev[i].rev2);
}
int main() {
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
solve();
return 0;
}