首页 > 代码库 > bzoj3781 小B的询问

bzoj3781 小B的询问

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3781

【题解】

将x^2差分成1+3+5+...+(x+x-1)即可莫队了。顺手3min码出来了(兹磁啊)

复杂度$O(n\sqrt{n})$

技术分享
# include <math.h>
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e4 + 10;
const int mod = 1e9+7;

int n, m, K, bl[M], t[M], a[M], B;
ll cnt, ans[M];

struct pa {
    int l, r, id;
    pa() {}
    pa(int l, int r, int id) : l(l), r(r), id(id) {}
    friend bool operator < (pa a, pa b) {
        return bl[a.l] < bl[b.l] || (bl[a.l] == bl[b.l] && bl[a.r] < bl[b.r]);
    }
}q[M];

inline void add(int x) {
    t[x] ++;
    cnt += (t[x] + t[x] - 1);
}

inline void del(int x) {
    cnt -= (t[x] + t[x] - 1);
    t[x] --;
}

int main() {
    cin >> n >> m >> K; B = 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;
    for (int i=1; i<=n; ++i) bl[i] = (i-1)/B+1;
    sort(q+1, q+m+1);
    int L = 1, R = 0;
    for (int i=1; i<=m; ++i) {
        while(R < q[i].r) ++R, add(a[R]);
        while(R > q[i].r) del(a[R]), --R;
        while(L < q[i].l) del(a[L]), ++L;
        while(L > q[i].l) --L, add(a[L]);
        ans[q[i].id] = cnt;
    }
    for (int i=1; i<=m; ++i) printf("%lld\n", ans[i]);
    return 0;
}
View Code

 

bzoj3781 小B的询问