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
Has the following properties:
- 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
- The sum of the interval [fx,x] is dis[x]
- The sum of the interval [fy,y] is dis[y]
When the merge can be obtained:
-
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()