博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
51 nod 1681 公共祖先 (主席树+dfs序)
阅读量:7080 次
发布时间:2019-06-28

本文共 3896 字,大约阅读时间需要 12 分钟。

1681 公共祖先

基准时间限制:1 秒 空间限制:131072 KB 分值: 80 难度:5级算法题
 

有一个庞大的家族,共n人。已知这n个人的祖辈关系正好形成树形结构(即父亲向儿子连边)。

在另一个未知的平行宇宙,这n人的祖辈关系仍然是树形结构,但他们相互之间的关系却完全不同了,原来的祖先可能变成了后代,后代变成的同辈……

两个人的亲密度定义为在这两个平行宇宙有多少人一直是他们的公共祖先。

整个家族的亲密度定义为任意两个人亲密度的总和。

Input
第一行一个数n(1<=n<=100000)接下来n-1行每行两个数x,y表示在第一个平行宇宙x是y的父亲。接下来n-1行每行两个数x,y表示在第二个平行宇宙x是y的父亲。
Output
一个数,表示整个家族的亲密度。
Input示例
51 33 55 44 21 21 33 41 5
Output示例
6

 

/*51 nod 1681 公共祖先 (主席树+dfs序)problem:给你两棵树, 两个节点之间的值定义为在两个棵树中有多少一直是它们的公共祖先求任意两个点的亲密度的总和solve:问题可以转换成每个点能够成为多少次公共祖先. 如果lca一直是a,b的公共祖先, 那么a,b一定在lca的子树中.    所以找出两棵树中lca点的子树中的相同点的个数,就能计算出多少对点在两棵树中都有lca这个公共祖先.先处理出a树的dfs序,然后用其作为b树中dfs序的值. 在a树中,如果u在lca的子树中,那么它的序号大于dfa[lca]小于等于eda[lca],即进出值. 所以在b树的lca的子树中找出序号在[dfa[lca],eda[lca]]之间的个数(可以主席树维护), 就是lca子树所含相同点的个数.hhh-2016/09/16-11:36:14*/#pragma comment(linker,"/STACK:124000000,124000000")#include 
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#define lson i<<1//#define rson i<<1|1#define ll long long#define clr(a,b) memset(a,b,sizeof(a))#define scanfi(a) scanf("%d",&a)#define scanfs(a) scanf("%s",a)#define scanfl(a) scanf("%I64d",&a)#define scanfd(a) scanf("%lf",&a)#define key_val ch[ch[root][1]][0]#define eps 1e-7#define inf 0x3f3f3f3f3f3f3f3fusing namespace std;const ll mod = 1e9+7;const int maxn = 100010;const double PI = acos(-1.0);template
void read(T&num){ char CH; bool F=false; for(CH=getchar(); CH<'0'||CH>'9'; F= CH=='-',CH=getchar()); for(num=0; CH>='0'&&CH<='9'; num=num*10+CH-'0',CH=getchar()); F && (num=-num);}int stk[70], tp;template
inline void print(T p){ if(!p) { puts("0"); return; } while(p) stk[++ tp] = p%10, p/=10; while(tp) putchar(stk[tp--] + '0'); putchar('\n');}struct Edge{ int to,next;};Edge edge[maxn*2];int tot,head[maxn];int in[maxn];int cnt;void ini(){ tot = 0; cnt = 0; memset(in,0,sizeof(in)); memset(head,-1,sizeof(head));}void add_edge(int u,int v){ edge[tot].to = v; edge[tot].next = head[u]; head[u] = tot++;}int dfa[maxn],dfb[maxn],ta[maxn],tb[maxn];int eda[maxn],edb[maxn];void dfs(int u,int pre,int flag){ if(!flag) dfa[u] = ++ cnt, ta[u] = cnt; else dfb[u] = ++ cnt, tb[cnt] = ta[u]; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].to; if(v == pre)continue; dfs(v,u,flag); } if(!flag) eda[u] = cnt; else edb[u] = cnt;}int toa;int lson[maxn * 30],rson[maxn * 30] ;ll c[maxn * 30];int build(int l,int r){ int root = toa ++ ; c[root] = 0; if(l != r) { int mid = (l+r) >> 1; build(l,mid); build(mid+ 1,r); } return root ;}int n;int update(int root,int pos,ll val){ int newroot = toa ++ ,tmp = newroot; c[newroot ] = c[root] + val; int l = 1,r = n; while(l < r) { int mid = (l+r) >> 1; if(pos <= mid) { lson[newroot] = toa ++ ,rson[newroot] = rson[root]; newroot = lson[newroot],root = lson[root]; r = mid; } else { rson[newroot] = toa ++ ,lson[newroot] = lson[root]; newroot = rson[newroot] ,root = rson[root]; l = mid + 1; } c[newroot] = c[root] + val; } return tmp;}ll query(int root1,int root2,int la,int ra,int l,int r){ if(l >= la && r <= ra) { return c[root2] - c[root1]; } int mid = (l + r) >> 1; ll ans = 0; if(la <= mid) { ans += query(lson[root1],lson[root2],la,ra,l,mid); } if(ra > mid) { ans += query(rson[root1],rson[root2],la,ra,mid+1,r); } return ans;}void cal(int flag){ int u,v; ini(); for(int i = 1; i < n; i++) { read(u),read(v); add_edge(u,v); add_edge(v,u); in[v] ++ ; } for(int i = 1; i <= n;i++) { if(!in[i]) { dfs(i,-1,flag); break; } }}int T[maxn];int main(){// freopen("in.txt","r",stdin); read(n); toa = 0; cal(0); cal(1); T[0] = build(1,n); for(int i = 1;i <= n;i++) { T[i] = update(T[i-1],tb[i],1); } ll ans = 0; for(int i = 1;i <= n;i++) { int l = dfb[i],r = edb[i]; ll t = query(T[l],T[r],dfa[i],eda[i],1,n); ans += 1LL*t*(t-1)/2; } printf("%I64d\n",ans); return 0;}

  

转载于:https://www.cnblogs.com/Przz/p/5876183.html

你可能感兴趣的文章
整理了一些t-sql技巧
查看>>
一键安装docker-ce
查看>>
java mybatis使用 设置resultType查询对象字段为null
查看>>
【转】mysql对large page的支持
查看>>
11-unittest
查看>>
学习OpenSeadragon之四(导航视图)
查看>>
PHP表单数据写入MySQL代码
查看>>
ASP.NET:Session对并发访问的影响
查看>>
Insertion sort list
查看>>
centos7 安装java+tomcat
查看>>
Uncaught TypeError: form.attr is not a function 解决办法
查看>>
HDU 1023 Train Problem II( 大数卡特兰 )
查看>>
图片的画图板
查看>>
Activex、OLE、COM、OCX、DLL之间的区别(转)
查看>>
MYSQL远程登录权限设置 ,可以让Navicat远程连接服务器的数据库
查看>>
ajax跨域
查看>>
Linux下Tomcat复制一个新的文件夹后无法启动的问题
查看>>
Linux编程 16 文件权限(组管理 groupadd, groupmod,文件权限介绍)
查看>>
hdu5521 Meeting
查看>>
android学习笔记之handler(2)
查看>>