Problem:
Problem D: Room of Time and Spirit

Problem

　20XX年、とある科学者がバイオテクノロジーによって強力な人造人間を開発してしまった。この人造人間はコンピュータにより、戦闘の達人たちの細胞を組み合わせて作られているため非常に強力である。

　このままでは地球は人造人間に支配されてしまうので、 N 人の戦士たちは人造人間と戦うことにした。しかし今の戦士たちでは到底人造人間に敵わないため、修行をしなければならない。また、N 人の戦士たちはそれぞれ 1 ~ N の番号が付いている。

　この時代、天空都市AIZUには SRLU室と呼ばれる修行のための特殊な部屋が存在した。この部屋での1年は外界の時間の1日と同じであるため、短期間で戦闘力を大幅に上昇することが出来る。同時に部屋に入れる人数の上限は2人である。また、その2人が部屋に入った時、それぞれ戦闘力が上昇する。

　戦士たちは残された時間でどのように部屋に入るか検討するため、あなたに以下のクエリを処理するプログラムの作成を依頼した。

　与えられるクエリは以下の通りである。

　また以下の説明で出てくる A, B はそれぞれ戦士の番号を表す。A と B が等しい事は無い。

IN A B C

　A と B が部屋に入り、それぞれ C だけ戦闘力が上昇する。この時、(部屋に入る直前の B の戦闘力) - (部屋に入る直前の A の戦闘力) = C が成り立つ。また、この時 B の戦闘力は A の戦闘力より高い事が保証される。

COMPARE A B

　A と B の戦闘力の差 (現在の B の戦闘力) - (現在の A の戦闘力)を出力する。もしその差が特定出来なければ、WARNING と出力せよ。

Input

N Q
query1
.
.
.
queryQ

最初に戦士の人数 N , クエリの数 Q が与えられる。

次に Q 回だけクエリが与えられる。

Constraints

入力は以下の条件を満たす。

2 ≤ N ≤ 100000

1 ≤ Q ≤ 100000

1 ≤ A, B ≤ N

1 ≤ C ≤ 5000

Output

上記のように与えられたクエリを順番に処理していき、 COMPAREの入力が与えられた際に出力を行う。

Sample Input1

3 5
COMPARE 1 2
IN 1 2 5
IN 2 3 3
COMPARE 2 3
COMPARE 1 3

Sample Output1

WARNING
3
11

Sample Input2

4 3
IN 1 4 10
IN 2 3 20
COMPARE 1 2

Sample Output2

WARNING

Sample Input3

3 4
IN 2 1 2
IN 3 1 2
COMPARE 1 3
COMPARE 2 3

Sample Output3

-2
2

Sample Input4

10 4
IN 10 8 2328
IN 8 4 3765
IN 3 8 574
COMPARE 4 8

Sample Output4

-3191

Sample Input5

3 5
IN 1 2 5
IN 1 2 5
IN 2 3 10
COMPARE 1 2
COMPARE 2 3

Sample Output5

15
10

Solution in C (judge verdict: Accepted)

// AOJ 1519: Room of Time and Spirit
// 2017.12.3 bal4u@uu

#include <stdio.h>
#include <string.h>

// <????????????Union Find>
#define MAX 100003

int power[MAX];
int par[MAX], ws[MAX];

int find(int x)
{
	int p;
	if (par[x] < 0) return x;
    p = find(par[x]), ws[x] += ws[par[x]];
    return par[x] = p;
}
    
int weight(int x)
{
    find(x); 
    return ws[x];
}
    
int unite(int x, int y, int w)  // x <-(w)- y (x + w = y)
{
	int tmp;

//  w += weight(x), w -= weight(y);
    w += power[x] + weight(x), w -= power[y] + weight(y);
    x = find(x), y = find(y);
    if (x == y) return 0;
    if (par[y] < par[x]) // ???????????????????????????????????????????????????.
        tmp = x, x = y, y = tmp, w = -w;
    
    par[x] += par[y], par[y] = x;
    ws[y] = w;
    return 1;
}
    
int same(int x, int y)
{
	return find(x) == find(y);
}

// *ans = x - y. ?????????????????? return 0.
int diff(int *ans, int x, int y)
{
    if (find(x) != find(y)) return 0;
	*ans = ws[x] - ws[y];
	return 1;
}
// </????????????Union Find>


char buf[40], *p;
int getint()
{
	int n = 0;
	while (*p >= '0') n = (n<<3) + (n<<1) + (*p++ & 0xf);
	p++;
	return n;
}

int main()
{
	int n, q, a, b, c;

	fgets(p=buf, 40, stdin);
	n = getint(), q = getint();
	memset(par, 0xff, (n+1)*sizeof(int));

	while (q--) {
		fgets(p=buf, 40, stdin);
		if (*p == 'I') {
			p += 3, a = getint(), b = getint(), c = getint();
			power[a] += c, power[b] += c;
			unite(a, b, c);
		} else {
			p += 8, a = getint(), b = getint();
			if (find(a) != find(b)) puts("WARNING");
			else printf("%d\n", (power[b]+ws[b]) - (power[a]+ws[a]));
		}
	}
	return 0;
}