And check the set - crystal ball (nkoj2105)

Union lookup - crystal ball ( nkoj2105 )

topic analysis

Dynamically maintain the sum of the interval [l,r]

Union lookup combined with prefix sum

Utilize ordinal unions and prefix sums

Here, the sum of the interval from the i node to its parent fi is denoted dis[i], and the prefix sum of x is denoted as S x

Has the following properties:

  • S x S and = p The difference between the prefix sum of x and the prefix sum of y, that is, the sum of the interval [y, x] is p
  • d i s [ x ] = S x S f x The sum of the interval [fx,x] is dis[x]
  • d i s [ and ] = S and S f and The sum of the interval [fy,y] is dis[y]

When the merge can be obtained:

  • d i s [ f x ] = S f x S f and = d i s [ x ] + d i s [ and ] + p That is, the sum of the [fx, fy] interval ([fx, ffx] interval) is-dis[x] + dis[y] + p

In this way, the serial number is maintained. If two nodes belong to the same heap, the sum of the intervals they consist of can be obtained.

code

//
// Created by rv on 2018/4/20.
//

#include "cstdio"
#include "map"

using namespace std;

struct UF {
    int count;
    int* father;
    int* dis;
    UF(int t) {
        count  = t;
        father = new int[t];
        dis = new int[t];
        for (int i = 0; i < t; i++) {
            father[i] = i;
            dis[i] = 0;
        }
    }
    int get_father(int x) {
        if (father[x] == x) {
            return x;
        } else {
            int tmp = get_father(father[x]);
            dis[x] += dis[father[x]];
            father[x] = tmp;
            return father[x];
        }
    }
    void merge(int x, int y, int p) {
        int fx = get_father(x);
        int fy = get_father(y);
        father[fx] = fy;
        dis[fx] = - dis[x] + dis[y] + p;
    }
    void check(int x, int y, int p) {
        int fx = get_father(x);
        int fy = get_father(y);
        if (fx == fy) {
            int can_p = dis[x] - dis[y];
            if (can_p != p) {
                printf("Bug Detected %d\n", can_p);
            } else {
                printf("Accept\n");
            }
        } else {
            merge(x, y, p);
            printf("Accept\n");
        }
    }
    void print() {
        printf("father: ");
        for (int i = 0; i < count; i++) {
            printf("%d ", father[i]);
        }
        printf("\n");
        // printf("size: ");
        // for (int i = 0; i < count; i++) {
            // printf("%d ", size[i]);
        // }
        // printf("\n");
        printf("dis: ");
        for (int i = 0; i < count; i++) {
            printf("%d ", dis[i]);
        }
        printf("\n");
    }
};

int main() {
//    freopen("1206/data2.in", "r", stdin);
//    freopen("data2.out", "w", stdout);
    int M, l, r, p;
    scanf("%d", &M);
    UF uf(2 * M + 1);
    map<int, int> mp;
    while(M--) {
        scanf("%d%d%d", &l, &r, &p);
        // printf("l=%d r=%d p=%d\n", l, r, p);
        if (mp.find(r) == mp.end()) {
            mp[r] = mp.size();
        }
        if (mp.find(l - 1) == mp.end()) {
            mp[l - 1] = mp.size();
        }
        uf.check(mp[r], mp[l - 1], p);
//        uf.print();
    }
    return 0;
}

PS

Since l and r are too large, it is better to use map mapping (discretization) and then use union search to process. The specific method ismp[i]=mp.size()

Guess you like

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