博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【BZOJ3772】精神污染 DFS序+主席树
阅读量:5088 次
发布时间:2019-06-13

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

【BZOJ3772】精神污染

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

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

HINT

100%的数据满足:N,M<=100000
(题意只有最后一句是有用的,其余都是废话。)
题解:理解一下:对于每一个询问x,y,将y的子树中的所有节点都加到x的子树中的所有线段树中去。
具体做法:离散化+DFS处理入栈出栈序+求LCA+主席树
#include 
#include
#include
#include
using namespace std;const int maxn=100010;int n,m,cnt,tot,nm;long long ans,dev;int to[maxn<<1],next[maxn<<1],head[maxn],qt[maxn],qn[maxn],qh[maxn],root[maxn<<1];int size[maxn],top[maxn],fa[maxn],son[maxn],deep[maxn],Q[maxn<<1],qin[maxn],qout[maxn];struct node{ int sum,ls,rs;}s[maxn*39];int readin(){ int ret=0,f=1; char gc=getchar(); while(gc<'0'||gc>'9') {if(gc=='-')f=-f;gc=getchar();} while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar(); return ret*f;}void add(int a,int b){ to[cnt]=b; next[cnt]=head[a]; head[a]=cnt++;}void dfs1(int x){ size[x]=1; Q[++Q[0]]=x; qin[x]=++nm; for(int i=head[x];i!=-1;i=next[i]) { if(to[i]!=fa[x]) { fa[to[i]]=x; deep[to[i]]=deep[x]+1; dfs1(to[i]); size[x]+=size[to[i]]; if(size[to[i]]>size[son[x]]) son[x]=to[i]; } } qout[x]=++nm;}void dfs2(int x,int tp){ top[x]=tp; if(son[x]) dfs2(son[x],tp); for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=son[x]&&to[i]!=fa[x]) dfs2(to[i],to[i]);}int getlca(int x,int y){ while(top[x]!=top[y]) { if(deep[top[x]]>deep[top[y]]) x=fa[top[x]]; else y=fa[top[y]]; } if(deep[x]>deep[y]) return y; return x;}void insert(int x,int &y,int l,int r,int pos,int val){ if(pos>r) return ; y=++tot; if(l==r) { s[y].sum=s[x].sum+val; return ; } int mid=l+r>>1; if(pos<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,pos,val); else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,pos,val); s[y].sum=s[s[y].ls].sum+s[s[y].rs].sum;}int query(int x1,int x2,int x3,int x4,int l,int r,int a,int b){ if(a<=l&&r<=b) return s[x1].sum+s[x2].sum-s[x3].sum-s[x4].sum; int mid=l+r>>1; if(b<=mid) return query(s[x1].ls,s[x2].ls,s[x3].ls,s[x4].ls,l,mid,a,b); if(a>mid) return query(s[x1].rs,s[x2].rs,s[x3].rs,s[x4].rs,mid+1,r,a,b); return query(s[x1].ls,s[x2].ls,s[x3].ls,s[x4].ls,l,mid,a,b)+ query(s[x1].rs,s[x2].rs,s[x3].rs,s[x4].rs,mid+1,r,a,b);}long long gcd(long long a,long long b){ return (b==0)?a:gcd(b,a%b);}int main(){ n=readin(),m=readin(); int i,j,a,b,c; memset(head,-1,sizeof(head)); for(i=1;i

转载于:https://www.cnblogs.com/CQzhangyu/p/6296432.html

你可能感兴趣的文章
solr后台操作Documents之增删改查
查看>>
http://yusi123.com/
查看>>
文件文本的操作
查看>>
Ubuntu linux下gcc版本切换
查看>>
记一次Web服务的性能调优
查看>>
jQuery.form.js使用
查看>>
(转)linux sort,uniq,cut,wc命令详解
查看>>
关于ExecuteNonQuery执行的返回值(SQL语句、存储过程)
查看>>
UVa540 Team Queue(队列queue)
查看>>
mysql数据增删改查
查看>>
akka之种子节点
查看>>
不知道做什么时
查看>>
matlab 给某一列乘上一个系数
查看>>
密码学笔记——培根密码
查看>>
Screening technology proved cost effective deal
查看>>
MAC 上升级python为最新版本
查看>>
创业老板不能犯的十种错误
查看>>
Animations介绍及实例
查看>>
判断请求是否为ajax请求
查看>>
【POJ2699】The Maximum Number of Strong Kings(网络流)
查看>>