题面在这里

题意:

给出一个树,共n个节点。
有m条互不相同的树上路径。
现在让你随机选择2条路径,问两条路径存在包含关系的概率(输出最简分数)。
n,m<=100000

做法:

假如我们把所有路径存下来,对于x,y的一条路,在x处打一个y标记,在y处打一个x标记,那么我们查询的时候,只要查询x,y两侧分别有多少标记就可以了,因为x,y两侧的点形成的路径肯定包含x-y。

再说得明白一点,就是假如你对每个点都开一棵线段树,每次假如x-y有一条路径,就在x的线段树上y的位子+1,在y的线段树上x的位子+1。假如现在有一个询问x-y,形象地看成x在左y在右,你就要询问x左侧所有点的线段树中y右侧所有位子的值的和。

然后我们考虑三种情况:

设x, y的lca为z。

1.假如x!=z且y!=z


x左侧相当于是x的子树,y右侧也相当于y的子树。

2.假如x,y中有一个=z


x左侧相当于是x的子树,y右侧相当于除去y在x路径上的儿子的子树外的部分。

3.假如x=y=z

那相当于只有一个点
x左侧相当于是x的子树,y右侧除去x子树的部分。

于是我们发现都涉及到了子树,而子树在dfs序上是连续的一段,所以我们跑出dfs序,用主席树/可持久化线段树维护。

最后注意代码细节即可。

代码

/*************************************************************Problem: bzoj 3772 精神污染 User: fengyuanLanguage: C++Result: AcceptedTime: 4764 msMemory: 63228 kbSubmit_Time: 2017-12-23 11:47:03
*************************************************************/#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cstdlib>
#define mid ((l+r)/2)
#define pb push_back
using namespace std;
typedef long long LL;const int N = 100010, M = 4000010;
int n, m, cnt, clk, tot;
int head[N], depth[N], f[N][19], in[N], out[N], L[M], R[M], rt[N], sum[M];
struct Edge{ int to, nex; }e[N<<1];
struct Questions{ int x, y; }que[N];
vector<int> vec[N];inline void add(int x, int y)
{e[++ cnt].to = y;e[cnt].nex = head[x];head[x] = cnt;
}inline void dfs(int u, int last, int s)
{depth[u] = s; f[u][0] = last; in[u] = ++ clk;for(int i = head[u]; i; i = e[i].nex)if(e[i].to != last) dfs(e[i].to, u, s+1);out[u] = clk;
}inline int LCA(int x, int y)
{if(depth[x] < depth[y]) swap(x, y);int tmp = depth[x] - depth[y];for(int i = 17; i >= 0; i --)if((tmp>>i)&1) x = f[x][i];if(x == y) return x;for(int i = 17; i >= 0; i --)if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];return f[x][0];
}inline void build(int &rt, int l, int r)
{rt = ++ tot; sum[rt] = 0;if(l == r) return;build(L[rt], l, mid); build(R[rt], mid+1, r);
}inline void update(int pre, int &rt, int l, int r, int x)
{if(!rt || rt == pre) rt = ++ tot, sum[rt] = sum[pre];sum[rt] ++;if(l == r) return;if(!L[rt]) L[rt] = L[pre];if(!R[rt]) R[rt] = R[pre];if(x <= mid) update(L[pre], L[rt], l, mid, x);else update(R[pre], R[rt], mid+1, r, x);
}inline int query(int u, int v, int l, int r, int x, int y)
{if(l == x && r == y) return sum[v]-sum[u];if(y <= mid) return query(L[u], L[v], l, mid, x, y);else if(x > mid) return query(R[u], R[v], mid+1, r, x, y);else return query(L[u], L[v], l, mid, x, mid) + query(R[u], R[v], mid+1, r, mid+1, y);
}inline bool isAncestor(int x, int y){ return in[x] <= in[y] && out[x] >= out[y]; }int main()
{scanf("%d%d", &n, &m);for(int i = 1; i < n; i ++) {int x, y; scanf("%d%d", &x, &y);add(x, y); add(y, x);}dfs(1, 0, 0);for(int j = 1; j <= 17; j ++)for(int i = 1; i <= n; i ++) f[i][j] = f[f[i][j-1]][j-1];for(int i = 1; i <= m; i ++) {int x, y; scanf("%d%d", &x, &y);if(in[x] > in[y]) swap(x, y);vec[in[x]].pb(in[y]);vec[in[y]].pb(in[x]);que[i].x = x; que[i].y = y;}build(rt[0], 1, n);for(int i = 1; i <= n; i ++) {rt[i] = rt[i-1];for(int j = 0; j < vec[i].size(); j ++)update(rt[i-1], rt[i], 1, n, vec[i][j]);}LL p = 0, q = 1LL*m*(m-1)/2;for(int i = 1; i <= m; i ++) {int x = que[i].x, y = que[i].y, z = LCA(x, y);if(x != z && y != z) {p += query(rt[in[x]-1], rt[out[x]], 1, n, in[y], out[y]);p --;} else if(x != z || y != z){if(y != z) swap(x, y);int t = x;for(int j = 17; j >= 0; j --)if(f[t][j] && !isAncestor(f[t][j], y)) t = f[t][j];p += query(rt[in[x]-1], rt[out[x]], 1, n, 1, n);p -= query(rt[in[x]-1], rt[out[x]], 1, n, in[t], out[t]);p --;} else {p += query(rt[in[x]-1], rt[out[x]], 1, n, 1, n);p -= query(rt[in[x]-1], rt[out[x]], 1, n, in[x], out[x]);}}LL g = __gcd(p, q);p /= g; q /= g;if(!p) puts("0"); else printf("%lld/%lld\n", p, q);return 0;
}

bzoj3772: 精神污染相关推荐

  1. [BZOJ3772]精神污染

    [BZOJ3772]精神污染 试题描述 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于 ...

  2. 【BZOJ3772】精神污染

    题解: 刚开始把题目看错了 以为没有给出路径 那我们就可以求极长路径为k的分别有多少条 可以上点分治+fft 是nlogn^2的 因为fft的范围和点分治后剩余的节点多少有关 正确的题目意思的话 我们 ...

  3. 主角有智能芯片的种田小说_推荐3本克苏鲁类小说,压抑邪恶与搞笑逗乐并存,看看是你的菜吗...

    有句老话说的真是太对了,人就是越呆越懒越吃越馋,本来只是单纯的找书断了一天更,结果就越来越懒了. <古神的自我修养> 作者 敖夜 状态 连载中 字数 144万字左右 克苏鲁.种田文.幕后黑 ...

  4. 深度有趣 | 22 天马行空的DeepDream

    2019独角兽企业重金招聘Python工程师标准>>> 简介 介绍DeepDream的原理并用TensorFlow实现 效果 先来看一下DeepDream的效果,本来是这样一张图片 ...

  5. 西南民大oj(矩阵快速幂)

    我的名字不可能那么难记 时间限制(普通/Java) : 1000 MS/ 3000 MS          运行内存限制 : 65536 KByte 总提交 : 16            测试通过 ...

  6. 《地狱之刃:塞娜的献祭》如何通过人物情感营造恐怖氛围?

    市面上多数恐怖游戏传达惊悚氛围的方式都大同小异,或暴力,或血腥,或突袭惊吓,或精神污染.但有那么一部分恐怖游戏,它们着重于刻画人物内心那不可名状的恐惧阴影,深入探索他们荒诞的精神世界,通过另一种视角去 ...

  7. [BZOJ5303] [HAOI2018] 反色游戏

    题目链接 LOJ:https://loj.ac/problem/2524 BZOJ:https://lydsy.com/JudgeOnline/problem.php?id=5303 洛谷:https ...

  8. 【UOJ574】多线程计算【二元二项式反演】【定积分】【矩阵】【NTT 卷积】

    题意:有 n×mn\times mn×m 的网格,每个结点在 [0,1)[0,1)[0,1) 内的一个随机时刻被点亮.有 hhh 个数对 xi,yix_i,y_ixi​,yi​,对于一个瞬间状态,如果 ...

  9. 【HNOI2016】序列【莫队】【单调栈】【ST表】

    题意:给定序列 aia_iai​,qqq 次询问 [l,r][l,r][l,r] 所有子区间最小值之和. n,q≤105n,q\leq 10^5n,q≤105 这种题一眼看上去是离线线段树,但这题每移 ...

  10. 【SCOI2014】方伯伯的商场之旅【数位dp】【单峰函数】

    题意:给定 l,r,kl,r,kl,r,k ,对于一个 kkk 进制数,将数码看成这个位置的石子个数,每将一个石子移动 111 的距离需要 111 的代价.求 [l,r][l,r][l,r] 中的所有 ...

最新文章

  1. 《深入浅出Ext JS》改版意见有奖征集活动!
  2. 五个超酷Linux命令
  3. qq昵称由fly改为思诺
  4. 卷积神经网络的“封神之路
  5. python3遍历选中文件夹下的文件【GUI编程】
  6. 使用CArchive类进行序列化
  7. 模拟UIWebView
  8. python接口自动化(五)--接口测试用例和接口测试报告模板(详解)
  9. C++基础语法-02-运算符重载
  10. 小学生python游戏编程_适合刚入门Python小白的趣味游戏编程
  11. STM32F103如何使用串口下载程序
  12. php cimage类,强大的多功能的用VB编写的高速图像处理库Cimage简介! - 小志的日志 - 电子工程世界-论坛...
  13. 北风网-Spark视频从入门到精通(高级特性、案例实战、内核源码、性能调优)-中华石杉老师
  14. intent传递集合数据
  15. Windows NT引导过程源代码分析(一)
  16. 未来已来,云上安全SaaS化势不可挡
  17. ISO/IEC 9126软件质量标准
  18. Python网络爬虫爬淘宝无法爬取问题的解决方法
  19. 华为 博士 实习_如何看待华为招聘生物博士实习生?
  20. 楚留香手游系统互通的服务器,楚留香手游帮派系统互通介绍

热门文章

  1. 谈谈 CGI、FastCGI、PHP-CGI、PHP-fpm
  2. 2021年高处安装、维护、拆除考试试卷及高处安装、维护、拆除操作证考试
  3. C-V2X 技术介绍
  4. 依图科技创始人:如何对AI技术和产业发展更全面的理解?
  5. C语言初学: 厘米换算英尺英寸
  6. 数理逻辑习题集(3)
  7. MonoGRNet: A Geometric Reasoning Network for Monocular 3D Object Localization
  8. 剑客之剑系列续篇:六脉神剑——PyCharm使用宝典
  9. VRPN-OSVR介绍
  10. 基于眨眼状态的在线疲劳检测系统(Matlab-GUI设计)