其他分享
首页 > 其他分享> > [国家集训队]小Z的袜子

[国家集训队]小Z的袜子

作者:互联网

Description

[国家集训队]小Z的袜子

Solution

又水了一道莫队题(练练手感)
对于询问,以左端点的块为第一关键字,右端点为第二关键字排序
用一个cnt数组储存从l到r这段区间中的各个颜色的数量
通过不断加减维护\(\sum^{m}_{i=1} \frac{cnt[color_i]*(cnt[color_i]-1)}{2}\)
和\(\frac{(q[i].len)\ast (q[i].len-1)}{2}\)除一个gcd就可以了

Code

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define ll long long
#define MAXN 500005
struct rec {
    ll l, r, num, base, x, y;
} q[MAXN];
ll n, m, BASE, l, r, ans;
ll c[MAXN], cnt[MAXN];
inline ll read() {
    ll s = 0, w = 1;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
    for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
    return s * w;
}
inline bool cmp1(rec x, rec y) {
    return (x.base == y.base) ? x.r < y.r : x.base < y.base;
}
inline bool cmp2(rec x, rec y) {
    return x.num < y.num;
}
ll gcd(ll x, ll y) {
    return !y ? x : gcd(y, x % y); 
} 
int main() {
    n = read(), m = read();
    BASE = sqrt(n);
    for (register ll i = 1; i <= n; i++)
        c[i] = read();
    for (register ll i = 1; i <= m; i++)
        q[i].l = read(), q[i].r = read(), q[i].num = i, q[i].base = q[i].l / BASE;
    sort(q + 1, q + m + 1, cmp1);
    //cnt[0] = 1;
    l = 1, r = 1, cnt[c[1]]++;
    for (register ll i = 1; i <= m; i++) {
        while (r < q[i].r) {
            r++;
            ans -= cnt[c[r]] * (cnt[c[r]] - 1);
            cnt[c[r]]++;
            ans += cnt[c[r]] * (cnt[c[r]] - 1);
        }
        while (r > q[i].r) {
            ans -= cnt[c[r]] * (cnt[c[r]] - 1);
            cnt[c[r]]--;
            ans += cnt[c[r]] * (cnt[c[r]] - 1);
            r--;
        }
        while (l < q[i].l) {
            ans -= cnt[c[l]] * (cnt[c[l]] - 1);
            cnt[c[l]]--;
            ans += cnt[c[l]] * (cnt[c[l]] - 1);
            l++;
        }
        while (l > q[i].l) {
            l--;
            ans -= cnt[c[l]] * (cnt[c[l]] - 1);
            cnt[c[l]]++;
            ans += cnt[c[l]] * (cnt[c[l]] - 1);
        }
        q[i].x = ans;
        q[i].y = (q[i].r - q[i].l + 1) * (q[i].r - q[i].l);
    }
    sort(q + 1, q + m + 1, cmp2);
    for (register ll i = 1; i <= m; i++)
        if (q[i].l == q[i].r) cout << 0 << "/" << 1 << endl;
        else
            cout << q[i].x / gcd(q[i].x, q[i].y) << "/" << q[i].y / gcd(q[i].x, q[i].y) << endl;
    return 0;
}

标签:cnt,袜子,ll,MAXN,ans,include,国家集训队,getchar
来源: https://www.cnblogs.com/Agakiss/p/11784643.html