您的位置:首页 > 其它

【bzoj 3615】MSS 分块 线段树的合并和拆分

2015-12-28 10:59 501 查看
二维坐标上有n个点,每维坐标互不相同。初始时每个点为一个独立的集合,要求维护:

合并两个集合

将集合id某一维以v为界拆分为两个集合

将集合x的数都加d

询问一个集合的sum,max,min

考虑按x坐标分块,对每个集合,每块建一个线段树。

/**************************************************************
Problem: 3615
User: hzt1
Language: C++
Result: Accepted
Time:18824 ms
Memory:375412 kb
****************************************************************/

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define Rep(i, x, y) for (int i = x; i <= y; i ++)
#define Dwn(i, x, y) for (int i = x; i >= y; i --)
#define RepE(i, x) for(int i = pos[x]; i; i = g[i].nex)
#define u t[x]
#define o t[y]
#define Tx t[tx]
#define Ty t[ty]
#define Lc t[ u.lc ]
#define Rc t[ u.rc ]
using namespace std;
typedef long long LL;
const int N = 51000, M = 110; const LL inf = 1LL << 60;
struct node { int x, y, z, n; } p
;
struct Seg_node { int lc, rc, x, sz; LL sum, mx, mn, lz; } t[N * M];
int n, ro[N * 4][M], cz, Q, qx, Bz, X
, l0
, r0
, q, B, Y
, bin[N * M], bz; char Type[8]; // In[N * M]
LL ans, mx, mn;
// long long ...
bool cmpx(node a, node b) { return a.x < b.x; }
bool cmpy(node a, node b) { return a.y < b.y; }
void Del(int x) { u.mx = -inf, u.mn = inf, u.lc = u.rc = u.x = u.sz = u.lz = u.sum = 0; bin[++ bz] = x; }
void PD(int x) {
if (!x) return ;
u.sum += u.lz * u.sz, Lc.lz += u.lz, Rc.lz += u.lz; u.mn += u.lz, u.mx += u.lz; u.lz = 0;
}
void Upd(int x) { u.sz = Lc.sz + Rc.sz, u.sum = Lc.sum + Rc.sum, u.mx = max(Lc.mx, Rc.mx), u.mn = min(Lc.mn, Rc.mn); }
void Build(int &x, int l, int r) {
x = bin[bz --], u.sz = 1, u.sum = u.mx = u.mn = p[q].z; // In[x]
if (l == r) { u.x = p[q].x; return ; }
int mid = l + r >> 1;
if (p[q].y <= mid) Build(u.lc, l, mid); else Build(u.rc, mid + 1, r);
}
void Split(int x, int &tx, int &ty, int l, int r) {
if (!x) return ; PD(x);
if (Y[r] <= q) { tx = x; return ; }
if (Y[l] > q) { ty = x; return ; }
tx = bin[bz --], ty = bin[bz --];
int mid = l + r >> 1;
Split(u.lc, Tx.lc, Ty.lc, l, mid), Split(u.rc, Tx.rc, Ty.rc, mid + 1, r);
Del(x); Upd(tx), Upd(ty);
}
int Merge(int x, int y) {
PD(x), PD(y);
if (!x || !y) return x + y;
u.lc = Merge(u.lc, o.lc), u.rc = Merge(u.rc, o.rc);
Del(y); Upd(x); return x;
}
void Sx(int x, int &tx, int &ty, int l, int r) {
if (!x) return ; PD(x);
if (l == r) { if (u.x <= q) tx = x; else ty = x; return ; }
int mid = l + r >> 1, lx, rx, ly, ry;
lx = rx = ly = ry = 0;
if (u.lc) Sx(u.lc, lx, ly, l, mid);
if (u.rc) Sx(u.rc, rx, ry, mid + 1, r);
Del(x);
if (lx || rx) tx = bin[bz --], Tx.lc = lx, Tx.rc = rx, Upd(tx);
if (ly || ry) ty = bin[bz --], Ty.lc = ly, Ty.rc = ry, Upd(ty);
}
int main()
{
scanf ("%d", &n), cz = n;
Rep(i, 1, N * M - 10) bin[i] = i, Del(i);
Del(0); bz = N * M - 10;
Rep(i, 1, n) {
scanf ("%d%d%d", &p[i].x, &p[i].y, &p[i].z); p[i].n = i;
}
sort(p + 1, p + n + 1, cmpy);
Rep(i, 1, n) Y[i] = p[i].y, p[i].y = i;
sort(p + 1, p + n + 1, cmpx);
// B = sqrt(n) + 1;
B = min(n, 600);
for (int i = 1; i <= n; i += B) {
Bz ++, l0[Bz] = i, r0[Bz] = min(i + B - 1, n);
Rep(j, i, r0[Bz]) {
X[j] = p[j].x;
q = j, Build(ro[ p[j].n ][Bz], 1, n);
}
}
// t[0].mn = inf;
scanf ("%d", &Q);
while (Q --) {
scanf ("%s", Type);
int x, y, d, v, z;
if (Type[0] == 'M') {
scanf ("%d%d", &x, &y);
Rep(i, 1, Bz) ro[x][i] = Merge(ro[x][i], ro[y][i]), ro[y][i] = 0;
// puts("fin");
} else if (Type[0] == 'S') {
scanf ("%d%d%d", &x, &d, &v);
if (!d) {
Rep(i, 1, Bz) {
if (v >= X[ r0[i] ]) ro[cz + 1][i] = ro[x][i];
else if (v < X[ l0[i] ]) ro[cz + 2][i] = ro[x][i];
else {
// nk += t[ ro[x][i] ].sz;
q = v, Sx(ro[x][i], ro[cz + 1][i], ro[cz + 2][i], 1, n);
}
ro[x][i] = 0;
}
} else {
q = v; Rep(i, 1, Bz) Split(ro[x][i], ro[cz + 1][i], ro[cz + 2][i], 1, n), ro[x][i] = 0;
}
cz += 2;
} else if (Type[0] == 'Q') {
scanf ("%d", &qx);
ans = 0, mx = -inf, mn = inf;
Rep(i, 1, Bz) {
x = ro[qx][i];
if (x) ans += u.sum, mx = max(mx, u.mx), mn = min(mn, u.mn);
}
printf("%lld %lld %lld\n", mx, mn, ans);
} else {
scanf ("%d%d", &qx, &z);
Rep(i, 1, Bz) {
x = ro[qx][i]; if (x) u.lz += z, PD(x);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: