【bzoj 3615】MSS 分块 线段树的合并和拆分
2015-12-28 10:59
501 查看
二维坐标上有n个点,每维坐标互不相同。初始时每个点为一个独立的集合,要求维护:
合并两个集合
将集合id某一维以v为界拆分为两个集合
将集合x的数都加d
询问一个集合的sum,max,min
考虑按x坐标分块,对每个集合,每块建一个线段树。
合并两个集合
将集合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; }
相关文章推荐
- JS获取页面宽度高度
- <LeetCode OJ> Happy Number【202】
- JAVA TCP/IP Socket 编程(一)
- iOS开发-21UINavigationController导航控制器初始化 导航控制器栈的push和pop跳转理解
- AFNetWorking
- 给UILabel设置不同的字体和颜色
- Object C中静态属性
- connect to a specific wifi network in Android programmatically
- 浅述Oracle用户表空间关【转】
- Android关于软键盘的若干
- zabbix------监控小技巧
- 本周工作计划2015/12/28
- HTML页面3秒后自动跳转的三种常见方法
- 前端基础知识
- ORACLE 临时表空间
- window filter platform (wfp)修改TCP数据包的方法
- 项目中自动加入类
- css绝对定位、相对定位和文档流的那些事
- Hdu 2086
- Codeforces Round #337 (Div. 2) B. Vika and Squares 贪心