51nod 1297 管理二叉树 (树分治)

来源:互联网 发布:通讯软件排名 编辑:程序博客网 时间:2024/06/05 20:05
#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[N];int fa[N];int fst[N], nxt[M], vv[M], e;int dep[N], sz[N], mx[N];int q[N], qh, qt;bool vis[N], tvis[N];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[N];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[N], y[N], xx[N], yy[N];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;}

0 0