51nod 1681 公共祖先 | 树状数组
2017-10-25 14:24
246 查看
51nod 1681 公共祖先
有一个庞大的家族,共n人。已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边)。
在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完全不同了,原来的祖先可能变成了后代,后代变成的同辈……
两个人的亲密度定义为在这两个平行宇宙有多少人一直是他们的公共祖先。
整个家族的亲密度定义为任意两个人亲密度的总和。
Input
第一行一个数n(1<=n<=100000)
接下来n-1行每行两个数x,y表示在第一个平行宇宙x是y的父亲。
接下来n-1行每行两个数x,y表示在第二个平行宇宙x是y的父亲。
Output
一个数,表示整个家族的亲密度。
Input示例
5
1 3
3 5
5 4
4 2
1 2
1 3
3 4
1 5
Output示例
6
先遍历第一棵树,按DFS序给每个节点标号,并记录每棵子树标号所处的范围的左端点 l[i] 和右端点 r[i]。
然后遍历第二棵树,分别记录遍历一棵子树前后 l[i]~r[i] 范围内有多少点被遍历过,设二者之差为x,ans += x * (x - 1) / 2 即可。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; template <class T> void read(T &x){ char c; while(c = getchar(), c < '0' || c > '9'); x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; } template <class T> void write(T x){ if(x >= 10) write(x / 10); putchar('0' + x % 10); } const int N = 100005; int n, l , r , idx, sum ; int ecnt, adj[2] , nxt[2] , go[2] ; ll ans; bool notroot ; void add(int u, int v, bool x){ notroot[v] = 1; go[x][++ecnt] = v; nxt[x][ecnt] = adj[x][u]; adj[x][u] = ecnt; } void dfs1(int u, int pre){ l[u] = ++idx; for(int e = adj[0][u]; e; e = nxt[0][e]) if(go[0][e] != pre) dfs1(go[0][e], u); r[u] = idx; } void change(int p){ while(p <= n) sum[p]++, p += p & -p; } int ask(int p){ int ret = 0; while(p) ret += sum[p], p -= p & -p; return ret; } void dfs2(int u, int pre){ change(l[u]); int old = ask(r[u]) - ask(l[u] - 1); for(int e = adj[1][u]; e; e = nxt[1][e]) if(go[1][e] != pre) dfs2(go[1][e], u); int now = ask(r[u]) - ask(l[u] - 1); int delta = now - old; ans += (ll) delta * (delta - 1) / 2; } int main(){ read(n); for(int i = 1, u, v; i < n; i++) read(u), read(v), add(u, v, 0); for(int i = 1; i <= n; i++) if(!notroot[i]) dfs1(i, 0); memset(notroot, 0, sizeof(notroot)); for(int i = 1, u, v; i < n; i++) read(u), read(v), add(u, v, 1); for(int i = 1; i <= n; i++) if(!notroot[i]) dfs2(i, 0); write(ans), putchar('\n'); return 0; }
相关文章推荐
- 51Nod 1681 公共祖先 [树状数组做法]
- 51nod 1681 公共祖先【树状数组】【DFS序】
- 【树链剖分】【树状数组】【最近公共祖先】【块状树】bzoj3631 [JLOI2014]松鼠的新家
- 51nod 1681 公共祖先
- 51Nod 1681 公共祖先 [主席树做法]
- 【DFS序+树状数组】51Nod 1681 公共祖先
- 51NOD1681 公共祖先 【dfs序+树状数组】
- [杂题 树状数组] 51Nod1681 公共祖先
- 51nod 1681 公共祖先 主席树dfs序
- 51nod 1681 公共祖先 (在这两个平行宇宙有多少人一直是他们的公共祖先)
- 51Nod-1681-公共祖先
- 51nod 1081 子段求和(树状数组)
- 51nod(1081 字段求和)(dp、树状数组、线段树求法)
- 1681 公共祖先
- poj 1330 【最近公共祖先问题+fa[]数组+ 节点层次搜索标记】
- ACM学习历程—51NOD 1685 第K大区间2(二分 && 树状数组 && 中位数)
- 51Nod 1672 扫描线 + 线段树/树状数组
- 51nod:公共祖先(主席树 & DFS序)
- [51Nod 1394 差和问题]树状数组
- 51Nod-1711平均数(二分+树状数组|线段树)