题目描述

兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海陆空交通设施发达。濑户内海沿岸气候温暖,多晴天,有日本少见的贸易良港神户港所在的神户市和曾是豪族城邑“城下町”的姬路市等大城市,还有以疗养地而闻名的六甲山地等。
兵库县官方也大力发展旅游,为了方便,他们在县内的N个旅游景点上建立了n-1条观光道,构成了一棵图论中的树。同时他们推出了M条观光线路,每条线路由两个节点x和y指定,经过的旅游景点就是树上x到y的唯一路径上的点。保证一条路径只出现一次。
你和你的朋友打算前往兵库县旅游,但旅行社还没有告知你们最终选择的观光线路是哪一条(假设是线路A)。这时候你得到了一个消息:在兵库北有一群丧心病狂的香菜蜜,他们已经选定了一条观光线路(假设是线路B),对这条路线上的所有景点都释放了【精神污染】。这个计划还有可能影响其他的线路,比如有四个景点1-2-3-4,而【精神污染】的路径是1-4,那么1-3,2-4,1-2等路径也被视为被完全污染了。
现在你想知道的是,假设随便选择两条不同的路径A和B,存在一条路径使得如果这条路径被污染,另一条路径也被污染的概率。换句话说,一条路径被另一条路径包含的概率。

输入

第一行两个整数N,M
接下来N-1行,每行两个数a,b,表示A和B之间有一条观光道。
接下来M行,每行两个数x,y,表示一条旅游线路。

输出

所求的概率,以最简分数形式输出。

样例输入

5 3
1 2
2 3
3 4
2 5
3 5
2 5
1 4

样例输出

1/3
样例解释
可以选择的路径对有(1,2),(1,3),(2,3),只有路径1完全覆盖路径2。

提示

100%的数据满足:N,M<=100000
 
  题目那么长,就最后一句有用QAQ。首先,一条路径A如果被另一条路径B覆盖,那么A路径的两端一定在B路径上。我们假设一条路径(x,y),x为起点,y为终点,对于每个点x存一下以它为起点的路径终点都有哪些,再维护整棵树的出栈入栈序,把出栈入栈序架在线段树上,然后再在原树上建主席树,每个点由父亲节点的主席树转移过来,在每个点对应的线段树上将以这个点为起点的所有终点在线段树上对应的出栈入栈位置+1或-1(入栈位置+1,出栈位置-1)。对于每条路径(x,y)的查询就是求两个点到它们lca的链所对应的主席树上按出栈入栈序区间求和。
  1. #include<map>
  2. #include<set>
  3. #include<queue>
  4. #include<cmath>
  5. #include<stack>
  6. #include<vector>
  7. #include<cstdio>
  8. #include<cstring>
  9. #include<iostream>
  10. #include<algorithm>
  11. #define mid ((L+R)>>1)
  12. using namespace std;
  13. int x,y;
  14. int n,m;
  15. int cnt;
  16. int num;
  17. int tot;
  18. int anc;
  19. long long ans;
  20. struct node
  21. {
  22. int x;
  23. int y;
  24. }q[100010];
  25. int d[100010];
  26. int in[100010];
  27. int to[200010];
  28. int l[4000010];
  29. int r[4000010];
  30. int out[100010];
  31. int sum[4000010];
  32. int next[200010];
  33. int head[100010];
  34. int root[100010];
  35. int f[100010][18];
  36. vector<int>v[100010];
  37. bool cmp(node a,node b)
  38. {
  39. if(a.x==b.x)
  40. {
  41. return a.y<b.y;
  42. }
  43. return a.x<b.x;
  44. }
  45. void add(int x,int y)
  46. {
  47. tot++;
  48. next[tot]=head[x];
  49. head[x]=tot;
  50. to[tot]=y;
  51. }
  52. long long gcd(long long x,long long y)
  53. {
  54. if(y==0)
  55. {
  56. return x;
  57. }
  58. return gcd(y,x%y);
  59. }
  60. int updata(int pre,int L,int R,int x,int k)
  61. {
  62. int rt=++cnt;
  63. if(L==R)
  64. {
  65. sum[rt]=sum[pre]+k;
  66. return rt;
  67. }
  68. l[rt]=l[pre];
  69. r[rt]=r[pre];
  70. if(x<=mid)
  71. {
  72. l[rt]=updata(l[pre],L,mid,x,k);
  73. }
  74. else
  75. {
  76. r[rt]=updata(r[pre],mid+1,R,x,k);
  77. }
  78. sum[rt]=sum[l[rt]]+sum[r[rt]];
  79. return rt;
  80. }
  81. int query(int x,int y,int fa,int anc,int L,int R,int ll,int rr)
  82. {
  83. if(ll==L&&rr==R)
  84. {
  85. return sum[x]+sum[y]-sum[fa]-sum[anc];
  86. }
  87. if(ll>mid)
  88. {
  89. return query(r[x],r[y],r[fa],r[anc],mid+1,R,ll,rr);
  90. }
  91. else if(rr<=mid)
  92. {
  93. return query(l[x],l[y],l[fa],l[anc],L,mid,ll,rr);
  94. }
  95. else
  96. {
  97. return query(l[x],l[y],l[fa],l[anc],L,mid,ll,mid)+query(r[x],r[y],r[fa],r[anc],mid+1,R,mid+1,rr);
  98. }
  99. }
  100. void dfs1(int x,int fa)
  101. {
  102. in[x]=++num;
  103. f[x][0]=fa;
  104. d[x]=d[fa]+1;
  105. for(int i=1;i<=17;i++)
  106. {
  107. f[x][i]=f[f[x][i-1]][i-1];
  108. }
  109. for(int i=head[x];i;i=next[i])
  110. {
  111. if(to[i]!=fa)
  112. {
  113. dfs1(to[i],x);
  114. }
  115. }
  116. out[x]=++num;
  117. }
  118. void dfs2(int x,int fa)
  119. {
  120. root[x]=root[fa];
  121. int len=v[x].size();
  122. for(int i=0;i<len;i++)
  123. {
  124. root[x]=updata(root[x],1,num,in[v[x][i]],1);
  125. root[x]=updata(root[x],1,num,out[v[x][i]],-1);
  126. }
  127. for(int i=head[x];i;i=next[i])
  128. {
  129. if(to[i]!=fa)
  130. {
  131. dfs2(to[i],x);
  132. }
  133. }
  134. }
  135. int lca(int x,int y)
  136. {
  137. if(d[x]<d[y])
  138. {
  139. swap(x,y);
  140. }
  141. int dep=d[x]-d[y];
  142. for(int i=0;i<=17;i++)
  143. {
  144. if(((1<<i)&dep))
  145. {
  146. x=f[x][i];
  147. }
  148. }
  149. if(x==y)
  150. {
  151.  
  152. return x;
  153. }
  154. for(int i=17;i>=0;i--)
  155. {
  156. if(f[x][i]!=f[y][i])
  157. {
  158. x=f[x][i];
  159. y=f[y][i];
  160. }
  161. }
  162. return f[x][0];
  163. }
  164. int main()
  165. {
  166. scanf("%d%d",&n,&m);
  167. for(int i=1;i<n;i++)
  168. {
  169. scanf("%d%d",&x,&y);
  170. add(x,y);
  171. add(y,x);
  172. }
  173. for(int i=1;i<=m;i++)
  174. {
  175. scanf("%d%d",&x,&y);
  176. v[x].push_back(y);
  177. q[i].x=x;
  178. q[i].y=y;
  179. }
  180. dfs1(1,0);
  181. dfs2(1,0);
  182. sort(q+1,q+m+1,cmp);
  183. for(int i=1;i<=m;i++)
  184. {
  185. x=q[i].x;
  186. y=q[i].y;
  187. anc=lca(x,y);
  188. ans+=query(root[x],root[y],root[anc],root[f[anc][0]],1,num,in[anc],in[x]);
  189. ans+=query(root[x],root[y],root[anc],root[f[anc][0]],1,num,in[anc],in[y]);
  190. ans-=query(root[x],root[y],root[anc],root[f[anc][0]],1,num,in[anc],in[anc]);
  191. ans--;
  192. }
  193. long long k=gcd(ans,1ll*m*(m-1)/2);
  194. long long g=1ll*m*(m-1)/2/k;
  195. ans/=k;
  196. printf("%lld/",ans);
  197. printf("%lld",g);
  198. }

BZOJ3772精神污染——可持久化线段树+出栈入栈序的更多相关文章

  1. 【bzoj4826】[Hnoi2017]影魔 单调栈+可持久化线段树

    题目描述 影魔,奈文摩尔,据说有着一个诗人的灵魂.事实上,他吞噬的诗人灵魂早已成千上万.千百年来,他收集了各式各样的灵魂,包括诗人.牧师.帝王.乞丐.奴隶.罪人,当然,还有英雄.每一个灵魂,都有着自己 ...

  2. 【BZOJ-3673&3674】可持久化并查集 可持久化线段树 + 并查集

    3673: 可持久化并查集 by zky Time Limit: 5 Sec  Memory Limit: 128 MBSubmit: 1878  Solved: 846[Submit][Status ...

  3. 【BZOJ-2653】middle 可持久化线段树 + 二分

    2653: middle Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1298  Solved: 734[Submit][Status][Discu ...

  4. 【BZOJ3207】花神的嘲讽计划I 可持久化线段树/莫队

    看到题目就可以想到hash 然后很自然的联想到可持久化权值线段树 WA:base取了偶数 这道题还可以用莫队做,比线段树快一些 可持久化线段树: #include<bits/stdc++.h&g ...

  5. 【BZOJ 3674】可持久化并查集加强版&【BZOJ 3673】可持久化并查集 by zky 用可持久化线段树破之

    最后还是去掉异或顺手A了3673,,, 并查集其实就是fa数组,我们只需要维护这个fa数组,用可持久化线段树就行啦 1:判断是否属于同一集合,我加了路径压缩. 2:直接把跟的值指向root[k]的值破 ...

  6. BZOJ-3524 Couriers 可持久化线段树

    可持久化线段树,其实就是类主席树了.. 3524: [Poi2014]Couriers Time Limit: 20 Sec Memory Limit: 128 MB Submit: 1124 Sol ...

  7. 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

    如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...

  8. BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )

    树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...

  9. HDU 5919 Sequence II(可持久化线段树)

    [题目链接]http://acm.hdu.edu.cn/showproblem.php?pid=5919 [题目大意] 给出一个数列,每次查询数列中,区间非重元素的下标的中位数.查询操作强制在线. [ ...

随机推荐

  1. Linux下ftp安装配置及三种用户的验证

    一.原理简介 二.安装配置 三.三种用户的验证 一.简介 FTP即文件传输协议(File Transfer Protocol),完成各主机的文件共享功能,基于客户端-服务器的协议,工作在应用层,tcp ...

  2. Django 学习 (第五部)

    表设计: from django.db import models # Create your models here. # class Foo(models.Model): # name = mod ...

  3. Notepad++中的颜色属性设置大全

    Indent guideline style  缩进参考线的颜色Brace highlight style 鼠标指针在框架左右时框架的颜色(如css中{}   js中的())Bad brace col ...

  4. 【终结版】C#常用函数和方法集汇总

    C#里面的常用的函数和方法非常重要,然而做题的时候会经常忘记这些封装好的方法,所以我总结一下 C#常用函数和方法集. [1]C#操作字符串的常用使用方法 在 C# 中,您可以使用字符数组来表示字符串, ...

  5. Nginx基于TCP/UDP端口的四层负载均衡(stream模块)配置梳理

    通过我们会用Nginx的upstream做基于http/https端口的7层负载均衡,由于Nginx老版本不支持tcp协议,所以基于tcp/udp端口的四层负载均衡一般用LVS或Haproxy来做.至 ...

  6. redis持久化策略梳理及主从环境下的策略调整记录

    redis是一个支持持久化的内存数据库,也就是说redis需要经常将内存中的数据同步到磁盘来保证持久化.可以不定期的通过异步方式保存到磁盘上(即“半持久化模式”):也可以把每一次数据变化都写入到一个A ...

  7. vue路由\导航刷新后:ative\localStorage\url截取参数

    <el-menu :default-active="$route.path" router mode="horizontal"> <el-me ...

  8. 【Beta阶段】第八次Scrum Meeting!

    每日任务内容: 本次会议为第八次Scrum Meeting会议~ 由于本次会议项目经理身体不适,未参与会议,会议精神由卤蛋代为转达,其他同学一起参与了会议 队员 昨日完成任务 明日要完成任务 刘乾 今 ...

  9. 初学Java必写的小程序。

    1.矩形面积,周长封装测试. /** * @author Administrator *封装好的矩形类 *自己私有的长宽属性 *开放 求面积求周长的方法 和设置长宽的方法 */ public clas ...

  10. 生命游戏&一维细胞自动机 笔记

    de 生命游戏是一种简单的聚合模型,展示了事物是如何聚合的,是自动机(CA)模型的一种.由剑桥大学约翰康威发明,其规则为: 1. 每个细胞拥有八个邻居,细胞状态只有存活(黑)和死亡(白)两种: 2.处 ...