Small Z socks "2009 National Team."

[Title] describes
as an undisciplined life of people, the small Z every morning takes a long time to find out from a pile of colorful socks in one pair to wear. Finally one day, the small Z can no longer tolerate this annoying process to find socks, so he decided resigned ......
Specifically, this small Z \ (N \) socks from \ (1 \) to \ (N \) number, then the number \ (L \) to \ (R & lt \) selecting two socks. Despite the small Z does not care two pair of socks is not complete, even two socks do not care whether either side, he is very concerned about the color of socks, after all, wearing two different colored socks will be very embarrassing.
Your task is to tell the small Z, how old he is able to get the same probability of two color socks. Of course, the small Z hope that this probability as high as possible, so that he may ask more than \ ((L, R) \ ) to facilitate their choice.

[Input format
input file contains the first line of two positive integers \ (N \) and \ (M \) . \ (N \) is the number of socks, \ (M \) the number of small Z mentioned in the inquiry. The next line contains the \ (N \) positive integers \ (C_i \) , where \ (C_i \) represents the \ (I \) represents the color of socks, the same color with the same numerals. The next \ (M \) rows, each row two positive integers \ (L, R \) represents a query.

[] Output format
comprising \ (M \) rows, for each row in the query output score \ (A / B \) represents from the interrogation interval \ ([L, R] \ ) randomly selected two socks Color the same probability. If the probability is \ (0 \) is output \ (0/1 \) , otherwise the output of \ (A / B \) must score the most simple.

answer

Mo teams algorithm, is simply a pointer to violence to maintain double the current query interval around each endpoint left or right pointer can move left or right one space at the same time the answer to the current update interval

We deal with the sort to ask if asked directly press row and press the left point right point arrangement is still likely to be stuck out through offline

Such inquiry \ ([2,2], [3,1000], [4,4], [5, 2000], [6,6] \) if in accordance with \ ([2,2], [4,4] , [6,6], [3,1000], [5, 2000] \) of the order of inquiry obviously right pointer will move many times less

So this idea of violence is to block the left point left point in the same \ (\ sqrt {n} \ ) query block precedence press the right endpoint is the priority ordering or ordering the left endpoint

Doing so each time the pointer moves only about approximately \ (\ sqrt {n} \ ) times the complexity is about \ (O (q \ sqrt { n}) \) is sufficient to this problem by

There is also a what is called parity block optimization method of inquiry seems to sort of even faster you can memorize the board

This question is specific as to how to do it. . . Suppose you want to add a color \ (x \) after being added to this section have \ (cnt [x] \) color \ (x \) then the answer is a legitimate number plus \ (cnt [x] -1 \
) if removed a color \ (x \) then subtract \ (cnt [x] \)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

ll read() {
    ll x = 0, f = 1; char ch = getchar();
    for (; ch > '9' || ch < '0'; ch = getchar()) if (ch == '-') f = -1;
    for (; ch <= '9' && ch >= '0'; ch = getchar()) x = (x << 1) + (x << 3) + (ch ^ '0');
    return x * f;
}

struct query{
    ll l, r, id;
} q[50005];

ll n, m, bl;
ll c[50005];
ll cnt[50005], ans, nl, nr;
ll ansx[50005], ansy[50005];

inline bool cmp(query a, query b) { //奇偶块排序
    if (a.l / bl == b.l / bl) {
        if ((a.l / bl) & 1) return a.r > b.r;
        else return a.r < b.r;
    } else return a.l < b.l;
}

inline bool cmp2(query a, query b) { //普通按块排序
        if (a.l / bl == b.l / bl) {
                return a.r < b.r;
        } else return a.l < b.l;
}

inline void add(ll x) {
    cnt[x]++;
    if (cnt[x] > 1) ans = ans + (cnt[x]-1);
}

inline void del(ll x) {
    cnt[x]--;
    if (cnt[x] > 0) ans = ans - cnt[x]; 
}

inline void update(ll l, ll r) {
    while (nl < l) del(c[nl++]);
    while (nl > l) add(c[--nl]);
    while (nr < r) add(c[++nr]);
    while (nr > r) del(c[nr--]);
}

inline void getans(ll x, ll y, ll id) {
    if (x == 0) {
        ansx[id] = 0; ansy[id] = 1;
        return;
    }
    ll gcd = __gcd(x, y);
    x /= gcd; y /= gcd;
    ansx[id] = x; ansy[id] = y;
}

int main() {
    n = read(); m = read();
    bl = sqrt(n);
    for (ll i = 1; i <= n; i++) {
        c[i] = read();
    }
    for (ll i = 1; i <= m; i++) {
        q[i].l = read(); q[i].r = read();
        q[i].id = i;
    }
    sort(q+1, q+m+1, cmp); nl = q[1].l, nr = q[1].r;
    for (ll i = q[1].l; i <= q[1].r; i++) {
        add(c[i]);
    }
    getans(ans, (nr-nl+1)*(nr-nl)/2, q[1].id);
    for (ll i = 2; i <= m; i++) {
        update(q[i].l, q[i].r);
        getans(ans, (nr-nl+1)*(nr-nl)/2, q[i].id);
    }
    for (ll i = 1; i <= m; i++) {
        printf("%lld/%lld\n", ansx[i], ansy[i]);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/ak-dream/p/AK_DREAM52.html