题意:在矩阵中有n个点,现有两种操作。Q x表示把x这个点所在行以及所在列的所有点都并到这个点上,并输出所有点移动距离的平方和。另外就是把某个点向某个方向移动若干位。
用两个 map<ll,set<ll>> m a p < l l , s e t < l l >> 分别存每行中点的集合和每列中点的集合,再用并查集的根节点存每个点所在的集合。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll maxn = 200000 + 10;
const ll MOD = 1e9 + 7;
ll par[maxn];
/*
ll find(ll x) {
if (x == par[x])
return x;
else
return par[x] = find(par[x]);
}
*/
ll find(ll x)
{
if (par[x] != x)
par[x] = find(par[x]);
return par[x];
}
struct Node {
ll x, y;
ll num;
Node() {}
Node(ll _x, ll _y, ll _num): x(_x), y(_y), num(_num) {}
} node[maxn];
ll n, m;
ll ans = 0;
ll cnt = 0;
ll T;
char s[5];
map < ll, set<ll> > sX;
map < ll, set<ll> > sY;
ll rt, tx, ty, tnum, tmp, a, b, x, y;
int main() {
scanf("%lld %lld", &n, &m);
sX.clear();
sY.clear();
for (ll i = 1; i <= n; i++) {
scanf("%lld %lld", &node[i].x, &node[i].y);
sX[node[i].x].insert(i);
sY[node[i].y].insert(i);
// printf("%lld %lld %lld\n", i, node[i].x, node[i].y);
par[i] = i;
node[i].num = 1;
}
scanf("%lld", &T);
ans = 0;
cnt = n + 1;
while (T--) {
scanf("%s", s);
if (s[0] == 'Q') {
scanf("%lld", &rt);
rt ^= ans;
// printf("== %lld\n", rt);
rt = find(rt);
// printf("== %lld\n", rt);
tx = node[rt].x;
ty = node[rt].y;
tnum = 0;
ans = 0;
set <ll>::iterator it;
for (it = sX[tx].begin(); it != sX[tx].end(); it++) {
// printf("%lld\n", *it);
tmp = abs(node[*it].y - ty);
tmp %= MOD;
// printf("it = %lld tmp = %lld num = %lld\n", *it, tmp, node[*it].num);
ans = (ans + tmp * tmp % MOD * node[*it].num % MOD + MOD) % MOD;
tnum += node[*it].num;
par[*it] = cnt;
sY[node[*it].y].erase(*it);
}
// printf("============================\n");
for (it = sY[ty].begin(); it != sY[ty].end(); it++) {
// printf("%lld\n", *it);
tmp = abs(node[*it].x - tx);
tmp %= MOD;
// printf("it = %lld tmp = %lld num = %lld\n", *it, tmp, node[*it].num);
ans = (ans + tmp * tmp % MOD * node[*it].num % MOD + MOD) % MOD;
tnum += node[*it].num;
par[*it] = cnt;
sX[node[*it].x].erase(*it);
}
par[cnt] = cnt;
node[cnt] = Node(tx, ty, tnum);
sX[tx].clear();
sY[ty].clear();
sX[tx].insert(cnt);
sY[ty].insert(cnt);
cnt++;
printf("%lld\n", ans);
}
else {
scanf("%lld %lld", &a, &b);
a ^= ans;
// printf("== %lld\n",a);
rt = find(a);
// printf("=== %lld\n",rt);
// printf("=== %lld\n",find(4));
x = node[rt].x;
y = node[rt].y;
sX[x].erase(a);
sY[y].erase(a);
node[rt].num--;
if (node[rt].num == 0) {
sX[x].erase(rt);
sY[y].erase(rt);
}
if (s[0] == 'L') {
tx = x;
ty = y - b;
// printf("tx = %lld ty = %lld\n", tx, ty);
node[a] = Node(tx, ty, 1);
sX[tx].insert(a);
sY[ty].insert(a);
par[a] = a;
}
if (s[0] == 'R') {
tx = x;
ty = y + b;
node[a] = Node(tx, ty, 1);
sX[tx].insert(a);
sY[ty].insert(a);
par[a] = a;
}
if (s[0] == 'U') {
tx = x - b;
ty = y;
node[a] = Node(tx, ty, 1);
sX[tx].insert(a);
sY[ty].insert(a);
par[a] = a;
}
if (s[0] == 'D') {
tx = x + b;
ty = y;
node[a] = Node(tx, ty, 1);
sX[tx].insert(a);
sY[ty].insert(a);
par[a] = a;
}
}
}
}