[Snoi2017] A simple inquiry

Description
gives you a sequence ai of length N, 1≤i≤N and q groups of queries, each group of queries reads l1, r1, l2, r2, and
needs to output Sigma(get(l1,r1,x)*get(l2 ,r2,x))(x>=0)
get(l,r,x) indicates how many times the number x appears in the calculation interval [l,r].


Sample Input
5
1 1 1 1 1
2
1 2 3 4
1 1 4 4


Sample Output
4
1


It's Team Mo's problem again!
You can formulate it, it can become
Sigma(get(0,r1,x)*get(0,r2,x)+get(0,l1-1,x)*get(0,l2-1, x))-
get(0,r1,x)*get(0,l2-1,x)-get(0,r2,x)*get(0,l1-1,x))(x>=0)
So you say that one query is split into four queries each time you ask
get(0,hh,x)(x>=0).
So you can use Mo team to do this.


#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
int _min(int x, int y) {return x < y ? x : y;}

struct node {
    int l, r, kk, opt;
} q[210000];
int ans, a[110000];
int p1[110000], p2[110000];
int gg[110000];

bool cmp(node a, node b) {
    if(a.kk == b.kk) return a.r < b.r;
    return a.kk < b.kk;
}

void hl(int k, int o) {p1[a[k]] += o; ans += p2[a[k]] * o;}
void hr(int k, int o) {p2[a[k]] += o; ans += p1[a[k]] * o;}

int main() {
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    int m; scanf("%d", &m);
    int len = 0;
    int pp = sqrt(m * 4);
    for(int i = 1; i <= m; i++) {
        int l1, r1, l2, r2; scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
        q[++len].l = r1; q[len].r = r2; if(q[len].l > q[len].r) swap(q[len].l, q[len].r);
        q[len].opt = len; q[len].kk = _min(q[len].l / pp + 1, pp + 1);
        q[++len].l = l1 - 1; q[len].r = r2; if(q[len].l > q[len].r) swap(q[len].l, q[len].r);
        q[len].opt = len; q[len].kk = _min(q[len].l / pp + 1, pp + 1);
        q[++len].l = l1 - 1; q[len].r = l2 - 1; if(q[len].l > q[len].r) swap(q[len].l, q[len].r);
        q[len].opt = len; q[len].kk = _min(q[len].l / pp + 1, pp + 1);
        q[++len].l = l2 - 1; q[len].r = r1; if(q[len].l > q[len].r) swap(q[len].l, q[len].r);
        q[len].opt = len; q[len].kk = _min(q[len].l / pp + 1, pp + 1);
    }
    sort(q + 1, q + len + 1, cmp);
    int ll = 0, rr = 0;
    for(int i = 1; i <= len; i++) {
        for(int j = rr + 1; j <= q[i].r; j++) hr(j, 1);
        for(int j = rr; j > q[i].r; j--) hr(j, -1);
        for(int j = ll + 1; j <= q[i].l; j++) hl(j, 1);
        for(int j = ll; j > q[i].l; j--) hl(j, -1);
        ll = q[i].l, rr = q[i].r;
        if(q[i].opt % 2 == 1) gg[(q[i].opt - 1) / 4 + 1] += ans;
        else gg[(q[i].opt - 1) / 4 + 1] -= ans;
    }
    for(int i = 1; i <= m; i++) printf("%d\n", gg[i]);
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324525165&siteId=291194637