【bzoj3772】精神污染 STL+LCA+主席树
题目描述
输入
输出
样例输入
5 3
1 2
2 3
3 4
2 5
3 5
2 5
1 4
样例输出
1/3
题解
Orz PoPoQQQ
由题可知所求为能够覆盖的路径对数/总路径对数。
总对数=m*(m-1)/2,所以只要求能够覆盖的对数即可。
首先我们易知如果某条路径B的两个端点都在另一条路径A上,那么A必然会覆盖B,反之亦然。
那么问题就转化为求A中所有点在多少条B上。
我们设Bi为(xi,yi),则问题就是求对于所有xi,有多少个yi在A上。
可以先把所有xi对应的所有yi存起来,这里使用vector。
用主席树维护每个xi对应的yi,使用Dfs序,入栈位置+1,出栈位置-1。
那么直接查询[xA,yA]范围内数的个数即可。
当然,每条A不能直接使用Dfs序计算,需要拆成[xA,lca]和[yA,lca](用倍增lca解决,树剖也可以),再减去重复计算的[lca,lca]。
由于主席树是建立在每个节点的父亲上的,所以每棵树代表着[1,x],所求路径即为[1,xA]+[1,yA]-[1,lca]-[1,fa[lca]]。
当然自己包含自己是不行的,需要减去。
这样就可以求出能够覆盖的路径对数。
需要说明的是题目中已经声明没有重复路径,所以不需要去重。
最后求gcd再输出即可。
数组大小略坑。
#include <cstdio>
#include <vector>
#include <algorithm>
#define N 100010
using namespace std;
struct data
{
int x , y , lca;
}a[N];
vector<int> v[N];
int fa[N][20] , deep[N] , log[N] , head[N] , to[N * 2] , next[N * 2] , cnt;
int lp[N] , rp[N] , pl , q[N] , top;
int root[N * 2] , ls[N * 39] , rs[N * 39] , si[N * 39] , tot;
bool cmp(data a , data b)
{
return a.x == b.x ? a.y < b.y : a.x < b.x;
}
void add(int x , int y)
{
to[++cnt] = y;
next[cnt] = head[x];
head[x] = cnt;
}
void dfs(int x)
{
int i;
lp[x] = ++pl;
q[++top] = x;
for(i = head[x] ; i ; i = next[i])
{
if(to[i] != fa[x][0])
{
fa[to[i]][0] = x;
deep[to[i]] = deep[x] + 1;
dfs(to[i]);
}
}
rp[x] = ++pl;
}
int getlca(int x , int y)
{
int i;
if(deep[x] < deep[y]) swap(x , y);
for(i = log[deep[x] - deep[y]] ; i >= 0 ; i -- )
if(deep[x] - (1 << i) >= deep[y])
x = fa[x][i];
for(i = log[deep[x]] ; i >= 0 ; i -- )
if(fa[x][i] != fa[y][i])
x = fa[x][i] , y = fa[y][i];
return x == y ? x : fa[x][0];
}
void update(int x , int &y , int l , int r , int p , int a)
{
y = ++tot;
if(l == r)
{
si[y] = si[x] + a;
return;
}
int mid = (l + r) >> 1;
if(p <= mid) rs[y] = rs[x] , update(ls[x] , ls[y] , l , mid , p , a);
else ls[y] = ls[x] , update(rs[x] , rs[y] , mid + 1 , r , p , a);
si[y] = si[ls[y]] + si[rs[y]];
}
int query(int w , int x , int y , int z , int l , int r , int b , int e)
{
if(b <= l && r <= e)
return si[w] + si[x] - si[y] - si[z];
int mid = (l + r) >> 1 , sum = 0;
if(b <= mid) sum += query(ls[w] , ls[x] , ls[y] , ls[z] , l , mid , b , e);
if(e > mid) sum += query(rs[w] , rs[x] , rs[y] , rs[z] , mid + 1 , r , b , e);
return sum;
}
long long gcd(long long a , long long b)
{
return b ? gcd(b , a % b) : a;
}
int main()
{
int n , m , i , j , x , y;
long long A = 0 , B = 0 , T;
scanf("%d%d" , &n , &m);
for(i = 1 ; i < n ; i ++ )
scanf("%d%d" , &x , &y) , add(x , y) , add(y , x);
dfs(1);
for(i = 2 ; i <= n ; i ++ ) log[i] = log[i >> 1] + 1;
for(i = 1 ; i <= log[n] ; i ++ )
for(j = 1 ; j <= n ; j ++ )
if(deep[j] >= (1 << i))
fa[j][i] = fa[fa[j][i - 1]][i - 1];
for(i = 1 ; i <= m ; i ++ )
{
scanf("%d%d" , &a[i].x , &a[i].y);
a[i].lca = getlca(a[i].x , a[i].y);
v[a[i].x].push_back(a[i].y);
}
sort(a + 1 , a + m + 1 , cmp);
for(i = 1 ; i <= top ; i ++ )
{
x = q[i];
root[x] = root[fa[x][0]];
for(j = 0 ; j < (int)v[x].size() ; j ++ )
{
update(root[x] , root[x] , 1 , pl , lp[v[x][j]] , 1);
update(root[x] , root[x] , 1 , pl , rp[v[x][j]] , -1);
}
}
for(i = 1 ; i <= m ; i ++ )
{
A += query(root[a[i].x] , root[a[i].y] , root[a[i].lca] , root[fa[a[i].lca][0]] , 1 , pl , lp[a[i].lca] , lp[a[i].x]);
A += query(root[a[i].x] , root[a[i].y] , root[a[i].lca] , root[fa[a[i].lca][0]] , 1 , pl , lp[a[i].lca] , lp[a[i].y]);
A -= query(root[a[i].x] , root[a[i].y] , root[a[i].lca] , root[fa[a[i].lca][0]] , 1 , pl , lp[a[i].lca] , lp[a[i].lca]);
A -- ;
}
B = (long long)m * (m - 1) / 2;
T = gcd(A , B);
printf("%lld/%lld\n" , A / T , B / T);
return 0;
}
【bzoj3772】精神污染 STL+LCA+主席树的更多相关文章
- bzoj3772 精神污染 dfs 序+主席树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3772 题解 很简单的一道题目. 上午研究一个题目的时候发现了这个题目是一个弱化版,所以来写了一 ...
- 【BZOJ3772】精神污染 DFS序+主席树
[BZOJ3772]精神污染 Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是 ...
- BZOJ3772精神污染——可持久化线段树+出栈入栈序
题目描述 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户 ...
- BZOJ 3772: 精神污染(dfs序+主席树)
传送门 解题思路 比较神仙的一道题.首先计算答案时可以每条路径所包含的路径数,对于\(x,y\)这条路径,可以在\(x\)这处开个\(vector\)存\(y\),然后计算时只需要算这个路径上每个点的 ...
- LCA+主席树 (求树上路径点权第k大)
SPOJ 10628. Count on a tree (树上第k大,LCA+主席树) 10628. Count on a tree Problem code: COT You are given ...
- 【bzoj3123】[Sdoi2013]森林 倍增LCA+主席树+启发式合并
题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...
- [BZOJ3772]精神污染 主席树上树+欧拉序
3772: 精神污染 Time Limit: 10 Sec Memory Limit: 64 MB Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位 ...
- BZOJ3772 精神污染 【主席树 + dfs序】
题目 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海 ...
- BZOJ3772 精神污染 主席树 dfs序
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3772 题意概括 给出一个树,共n个节点. 有m条互不相同的树上路径. 现在让你随机选择2条路径,问 ...
随机推荐
- mybatis入门(一):jdbc的缺点
mybatis的基础内容 1.mybatis的框架原理 2.mybatis开发dao两种方法: a.原始dao开发方法(程序需要编写dao接口和dao实现类) b.mybatis的mapper接口(相 ...
- 20145234黄斐《信息安全系统设计基础》第六周学习总结(Y86模拟器的安装)
Y86模拟器的安装 由于本人的电脑有些问题,在安装的时候忽然断电导致之前的成果都没有截图. 1.安装bison和flex词法分析工具 sudo apt-get install bison flex t ...
- Codeforces Round #460 (Div. 2) 前三题
Problem A:题目传送门 题目大意:给你N家店,每家店有不同的价格卖苹果,ai元bi斤,那么这家的苹果就是ai/bi元一斤,你要买M斤,问最少花多少元. 题解:贪心,找最小的ai/bi. #in ...
- 北京Uber优步司机奖励政策(4月3日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 北京Uber优步司机奖励政策(9月14日~9月20日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
- 常用排序算法的C++实现
排序是将一组"无序"的记录序列调整为"有序"的记录序列. 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在 ...
- C#调用大漠插件,发送QQ和微信消息
大漠插件就不过多介绍了,不知道的请查下百度.主要是讲解C#怎么调用大漠插件. 大漠插件提供了COM版本,C#直接点击引用,添加即可.然后注册下大漠插件到系统文件夹,注册代码如下: static str ...
- php session存入redis
php的会话默认以文件的形式存在,可以配知道NOSQL中,既可以提高访问速度又能好好的实现回话共享,在后期做负载均衡时实现多台服务器session 同步也是比较方便: 一:在php配置文件中改 修改p ...
- OSG-简单模型控制
本文转至http://www.cnblogs.com/shapherd/archive/2010/08/10/osg.html 作者写的比较好,再次收藏,希望更多的人可以看到这个文章 互联网是是一个相 ...
- 【Python+OpenCV】人脸识别基于环境Windows+Python3 version_3(Anaconda3)+OpenCV3.4.3安装配置最新版安装配置教程
注:本次安装因为我要安装的是win10(64bit)python3.7与OpenCV3.4.3教程(当下最新版,记录下时间2018-11-17),实际中这个教程的方法对于win10,32位又或是64位 ...