博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ3772精神污染——可持久化线段树+出栈入栈序
阅读量:6008 次
发布时间:2019-06-20

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

题目描述

兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海陆空交通设施发达。濑户内海沿岸气候温暖,多晴天,有日本少见的贸易良港神户港所在的神户市和曾是豪族城邑“城下町”的姬路市等大城市,还有以疗养地而闻名的六甲山地等。
兵库县官方也大力发展旅游,为了方便,他们在县内的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的链所对应的主席树上按出栈入栈序区间求和。
#include#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mid ((L+R)>>1)using namespace std;int x,y;int n,m;int cnt;int num;int tot;int anc;long long ans;struct node{ int x; int y;}q[100010];int d[100010];int in[100010];int to[200010];int l[4000010];int r[4000010];int out[100010];int sum[4000010];int next[200010];int head[100010];int root[100010];int f[100010][18];vector
v[100010];bool cmp(node a,node b){ if(a.x==b.x) { return a.y
mid) { return query(r[x],r[y],r[fa],r[anc],mid+1,R,ll,rr); } else if(rr<=mid) { return query(l[x],l[y],l[fa],l[anc],L,mid,ll,rr); } else { 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); }}void dfs1(int x,int fa){ in[x]=++num; f[x][0]=fa; d[x]=d[fa]+1; for(int i=1;i<=17;i++) { f[x][i]=f[f[x][i-1]][i-1]; } for(int i=head[x];i;i=next[i]) { if(to[i]!=fa) { dfs1(to[i],x); } } out[x]=++num;}void dfs2(int x,int fa){ root[x]=root[fa]; int len=v[x].size(); for(int i=0;i
=0;i--) { if(f[x][i]!=f[y][i]) { x=f[x][i]; y=f[y][i]; } } return f[x][0];}int main(){ scanf("%d%d",&n,&m); for(int i=1;i

 

转载于:https://www.cnblogs.com/Khada-Jhin/p/9473384.html

你可能感兴趣的文章
sphinx是支持结果聚类的——WHERE、ORDER BY和GROUP BY
查看>>
ASP.NET 中设置路径的三种方式
查看>>
EBS使用 Distributed AD在多个节点并行adpatch
查看>>
windows添加和删除服务
查看>>
多年前写的一个ASP.NET网站管理系统,到现在有些公司在用
查看>>
关于云栖,有点无语的几个地方,管理能不能管?
查看>>
Windows线程的同步与互斥
查看>>
iOS:百度长语音识别具体的封装:识别、播放、进度刷新
查看>>
内核随记(三)--同步(1)【转】
查看>>
C#进阶系列——MEF实现设计上的“松耦合”(四):构造函数注入
查看>>
MP3是什么
查看>>
AngularJs ng-change事件/指令(转)
查看>>
谈谈设计模式~原型模式(Prototype)
查看>>
[Android Pro] service中显示一个dialog 或者通过windowmanage显示view
查看>>
linux内核数据结构之kfifo【转】
查看>>
COGS 144. [USACO Dec07] 魅力手镯【01背包复习】
查看>>
COM组件开发实践(三)
查看>>
word2007插件开发经验备忘2--如何操作word
查看>>
如何Windows分页控件中增加统计功能
查看>>
ExpandableListView 箭头样式
查看>>