【BestCoder19 D】hdu5111:Alexandra and Two Trees
2014-11-26 15:34
351 查看
【算法】
树链剖分,主席树。大部分按照官方题解:
先考虑在序列上而非树上的情况。设两个序列是a和b。 我们容易找到一个函数f,使得对于任意的i满足f(a[i])=i,并且f(其他)=0。然后把每个b[i]变成f(b[i])。这样就把a变成了1,2,...,n,而原问题的答案不变。 现在问题变成了:每次问b[u2..v2]中,值是u1..v1的元素的个数。这是数据结构的经典题目,可以用线段树或树状数组(离线)或可持久化线段树(在线)做。 对于树上的问题,设两个树是A和B。 我们不可能变换树A使得每次询问在A中都是一段连续区间,但是如果对A进行轻重链剖分,使得每个链的f值是连续的,就能保证每次询问至多查询O(log n)个区间。接下来就可以套用之前的方法用线段树或树状数组(离线)或可持久化线段树(在线)做了。
具体见代码实现。
【注意】
dfs会爆栈,需要扩大栈空间#pragma comment(linker, "/STACK:16777216")
【参考资料】
1、BestCoder官方题解【代码】
代码不算长,至少是已提交的几个里最短的。但是时间貌似有点长,估计大部分用在了memset上了。#pragma comment(linker, "/STACK:16777216") #include <iostream> #include <stdio.h> #include <stdlib.h> #include <algorithm> #include <math.h> #include <string.h> #define MEM(a) memset(a,0,sizeof(a)) #define mid ((l+r)>>1) #define lch lc[c] #define rch rc[c] #define F(i,x) for (i=head[x];i;i=e[i].next) const int MAXN = 100010; const int MAXNODE = 2000010; using namespace std; int n1, n2, num[3][MAXN], ll, rr; int lc[MAXNODE], rc[MAXNODE], s[MAXNODE], root[MAXN], numn; int i1[MAXN][2], i2[MAXN][2], cnt1, cnt2; struct chaindevide { int f[MAXN], son[MAXN], s[MAXN], dep[MAXN], top[MAXN], h[MAXN], g[MAXN], v[MAXN], T, n; struct edge{ int u, next; }e[100010]; int nume, head[MAXN]; inline void add(int x, int u){ e[++nume].u = u, e[nume].next = head[x], head[x] = nume; } void init(){ dep[1] = 1; } void dfs1(int c) { int i, t = 0; s[c] = 1; F(i, c) { if (f[c] == e[i].u) continue;//useless f[e[i].u] = c, dep[e[i].u] = dep[c] + 1; dfs1(e[i].u); s[c] += s[e[i].u]; if (s[e[i].u] > t) t = s[e[i].u], son[c] = e[i].u; } } void dfs2(int c, int tp) { int i; g[c] = ++T; h[T] = c; top[c] = tp; if (!son[c]) return; dfs2(son[c], tp); F(i, c) if (e[i].u != f[c] && e[i].u != son[c]) dfs2(e[i].u, e[i].u); } void read(int _n) { int i; n = _n; for (i = 2; i <= n; ++i) scanf("%d", &f[i]), add(f[i], i); for (i = 1; i <= n; ++i) scanf("%d", &v[i]); dfs1(1); dfs2(1, 1); } void divide(int ii[][2], int &cnt, int u, int v) { if (u == v) { ++cnt; ii[cnt][0] = ii[cnt][1] = g[u]; return; } while (top[u] != top[v]) { if (dep[top[u]] < dep[top[v]]) swap(u, v); ii[++cnt][0] = g[top[u]]; ii[cnt][1] = g[u]; u = f[top[u]]; } ii[++cnt][0] = min(g[u], g[v]); ii[cnt][1] = max(g[u], g[v]); } }T[3]; struct aa{ int num, pos, v; friend bool operator <(aa a, aa b){ return a.num < b.num || (a.num == b.num&&a.pos < b.pos); } void init(int _n, int _p, int _v){ num = _n, pos = _p, v = _v; } }a[200020]; void insert(int &c, int l, int r, int x) { lc[numn + 1] = lch, rc[numn + 1] = rch, c = ++numn; if (l == r) { s[c] = 1; return; } if (x <= mid) insert(lch, l, mid, x); else insert(rch, mid + 1, r, x); s[c] = s[lch] + s[rch]; } int query(int c, int l, int r) { if (ll <= l&&r <= rr) return s[c]; return ((ll <= mid) ? query(lch, l, mid) : 0) + ((rr > mid) ? query(rch, mid + 1, r) : 0); } void work() { int i, j, t = 0, q, u1, v1, u2, v2, ans = 0; T[1].read(n1); scanf("%d", &n2); T[2].read(n2); for (i = 1; i <= n1; ++i) a[++t].init(T[1].v[i], 0, T[1].g[i]); for (i = 1; i <= n1; ++i) T[1].v[i] = T[1].g[i]; for (i = 1; i <= n2; ++i) a[++t].init(T[2].v[i], i, 0); sort(a + 1, a + 1 + t); for (i = 1; i <= t; ++i) { if (!a[i].pos) continue; if (i > 1 && a[i].num == a[i - 1].num) T[2].v[a[i].pos] = a[i - 1].v; else T[2].v[a[i].pos] = 0; } for (i = 1; i <= n2; ++i) { root[i] = root[i - 1]; if (T[2].v[T[2].h[i]]) insert(root[i], 1, n1, T[2].v[T[2].h[i]]); } for (scanf("%d", &q); q; --q) { ans = 0; scanf("%d%d%d%d", &u1, &v1, &u2, &v2); T[1].divide(i1, cnt1 = 0, u1, v1); T[2].divide(i2, cnt2 = 0, u2, v2); for (i = 1; i <= cnt1; ++i) { ll = i1[i][0], rr = i1[i][1]; for (j = 1; j <= cnt2; ++j) ans += query(root[i2[j][1]], 1, n1) - query(root[i2[j][0] - 1], 1, n1); } printf("%d\n", ans); } } int main() { while (~scanf("%d", &n1)) { MEM(T); T[1].init(); T[2].init(); MEM(lc), MEM(rc), MEM(s), MEM(root); numn = 0; work(); } return 0; }
相关文章推荐
- 【HDU】5111 Alexandra and Two Trees 树链剖分+主席树【树上路径的交集】【在线算法】
- HDU 5111 Alexandra and Two Trees 树链剖分 + 主席树
- hdu 5111 Alexandra and Two Trees(树链剖分+函数式线段树)
- leetcode 617. Merge Two Binary Trees Python实现以及and操作符用法
- 【Leetcode】Merge Two Binary Trees 合并两个二叉树
- CodeForces 545E Paths and Trees(最短路)
- 【CodeForces 620D】Professor GukiZ and Two Arrays
- SCAU 2011 校赛 10307 Trees and Numbers
- Leetcode_two-sum (c++ and python version)
- 【Codeforces】-510B-Fox And Two Dots(dfs)
- Swift中推送通知设置:Binary operator '|' cannot be applied to two UIUserNotificationType operands 错误解决
- merge two column into one field in sql and hql
- Merge Two Binary Trees
- uva 10250 - The Other Two Trees
- CART Decision Tree and two pruning theory
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) D Bear and Two Paths
- 617. Merge Two Binary Trees
- Algorithm: Binary Tree(2) -- Special Trees (BST and Balanced Tree)
- Titanic challenge on Kaggle with decision trees (party) and SVMs (kernlab)
- LeetCode Add to List 617 Merge Two Binary Trees (深度优先搜索)