51nod 1297 管理二叉树 (树分治)
2016-08-06 13:17
323 查看
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> #include <cstdlib> #include <vector> #include <set> #include <assert.h> using namespace std; #define N 200020 #define M 500200 #define inf 0x3f3f3f3f #define mod 110119 #define LL long long #define ls (i << 1) #define rs (ls | 1) #define md (ll + rr >> 1) #define lson ll, md, ls #define rson md + 1, rr, rs #define MP make_pair #define pii pair<int, int> #define ui unsigned int #define fi first #define se second #define pll pair<LL, LL> int n, a ; int fa ; int fst , nxt[M], vv[M], e; int dep , sz , mx ; int q , qh, qt; bool vis , tvis ; LL sum[N * 20]; int cnt[N * 20]; int bk_cnt; struct node { int x, y, d; node() {} node(int x, int y, int d):x(x), y(y), d(d) {} }; vector<node> vt ; void init() { memset(fst, -1, sizeof fst); e = 0; } void add(int u, int v) { vv[e] = v, nxt[e] = fst[u], fst[u] = e++; } struct bst { int tag[N << 2]; int x , y , xx , yy ; void push_down(int i) { if(tag[i]) { tag[ls] = tag[rs] = tag[i]; tag[i] = 0; } } void update(int l, int r, int v, int ll, int rr, int i) { if(ll == l && rr == r) { tag[i] = v; return; } push_down(i); if(r <= md) update(l, r, v, lson); else if(l > md) update(l, r, v,rson); else update(l, md, v, lson), update(md + 1, r, v, rson); } int query(int x, int ll, int rr, int i) { if(tag[i]) return tag[i]; if(ll == rr) return 0; if(x <= md) return query(x, lson); return query(x, rson); } void insert(int v) { if(v == 1) { x[1] = 1, y[1] = n; } else { int p = query(a[v], 1, n, 1); if(a[v] < a[p]) { x[v] = x[p], y[v] = y[p]; } else x[v] = xx[p], y[v] = yy[p]; fa[v] = p; } yy[v] = y[v]; y[v] = a[v] - 1; xx[v] = a[v] + 1; if(x[v] <= y[v]) update(x[v], y[v], v, 1, n, 1); if(xx[v] <= yy[v]) update(xx[v], yy[v], v, 1, n, 1); } }BST; void bfs(int s) { qh = qt = 0; q[qt++] = s; tvis[s] = 1; dep[s] = 0; while(qh < qt) { int u = q[qh++]; for(int i = fst[u]; ~i; i = nxt[i]) { int v = vv[i]; if(vis[v] || tvis[v]) continue; tvis[v] = 1; dep[v] = dep[u] + 1; q[qt++] = v; } } for(int i = 0; i < qt; ++i) tvis[q[i]] = 0; } void divide(int s) { bfs(s); int rt = 0, tmp = inf; for(int i = qt - 1; i >= 0; --i) { int u = q[i]; sz[u] = 1; mx[u] = 0; for(int j = fst[u]; ~j; j = nxt[j]) { int v = vv[j]; if(dep[v] < dep[u] || vis[v]) continue; sz[u] += sz[v]; mx[u] = max(mx[u], sz[v]); } } for(int i = 0; i < qt; ++i) { int u = q[i]; mx[u] = max(mx[u], qt - sz[u]); if(mx[u] < tmp) tmp = mx[u], rt = u; } vis[rt] = 1; bfs(rt); int k = ++bk_cnt; vt[rt].push_back(node(k, -1, 0)); for(int i = fst[rt]; ~i; i = nxt[i]) { int v = vv[i]; if(vis[v]) continue; bfs(v); ++bk_cnt; for(int j = 0; j < qt; ++j) { int u = q[j]; vt[u].push_back(node(k, bk_cnt, dep[u] + 1)); } } for(int i = fst[rt]; ~i; i = nxt[i]) { int v = vv[i]; if(!vis[v]) divide(v); } } LL query(int u) { LL ret = 0; for(int i = 0; i < vt[u].size(); ++i) { int x = vt[u][i].x; int y = vt[u][i].y; int d = vt[u][i].d; ret += 1LL * cnt[x] * d + sum[x]; if(y != -1) ret -= 1LL * cnt[y] * d + sum[y]; } return ret; } void upd(int u) { for(int i = 0; i < vt[u].size(); ++i) { int x = vt[u][i].x; int y = vt[u][i].y; int d = vt[u][i].d; sum[x] += d; cnt[x] ++; if(y != -1) cnt[y] ++, sum[y] += d; } } int main() { scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } for(int i = 1; i <= n; ++i) { BST.insert(i); } init(); for(int i = 2; i <= n; ++i) { add(fa[i], i); add(i, fa[i]); } memset(vis, 0, sizeof vis); bk_cnt = 0; divide(1); LL ans = 0; for(int i = 1; i <= n; ++i) { if(i > 1) { ans += query(i); } upd(i); printf("%lld\n", ans); } return 0; }
相关文章推荐
- 51nod 1297 管理二叉树
- 【51NOD 1297】管理二叉树
- 51nod 1297 管理二叉树
- 51nod 1297 管理二叉树
- [51nod 1297]管理二叉树
- 51nod 1297 管理二叉树
- 51 nod 1297 管理二叉树
- 【51nod1297】【管理二叉树】【点分治】
- LintCode-分治-二叉树中的最大路径和
- 51nod 1348 乘积之和(NTT+分治)
- 51nod 1019 逆序数 (分治)
- 51nod1297 管理二叉树
- 51NOD 1376 最长递增子序列的数量 [CDQ分治]
- [分治 || 单调栈 单调队列] 51Nod 1215 数组的宽度
- [51nod1297]管理二叉树
- Chap02_递归与分治_判断两棵二叉树是否同构
- 51nod1297 管理二叉树
- 利用二叉树设计同学录管理系统
- 分治-二叉树重建
- 【BZOJ3648】寝室管理 树分治