传送门

解题思路

  比较神仙的一道题。首先计算答案时可以每条路径所包含的路径数,对于\(x,y\)这条路径,可以在\(x\)这处开个\(vector\)存\(y\),然后计算时只需要算这个路径上每个点的\(vector\)中的元素是否也在这条路径上。这个可以用主席树维护,主席树维护括号序列,进时\(+1\),出时\(-1\),然后加加减减算一下。这题卡空间。。

代码

#include<bits/stdc++.h>

using namespace std;
const int N=100005;
const int M=N*38;
typedef long long LL; inline int rd(){
int x=0,f=1; char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?0:1,ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
return f?x:-x;
} int n,m,head[N],cnt,to[N<<1],nxt[N<<1],xx[N],yy[N],siz[N],son[N];
int rt[N<<1],fa[N],top[N],in[N],num,out[N],tot,dep[N];
LL ans,sum;
vector<int> v[N]; struct Segment_Tree{
int ls[M],rs[M],sum[M];
void build(int &x,int l,int r){
x=++tot; if(l==r) return ;
int mid=(l+r)>>1;
build(ls[x],l,mid); build(rs[x],mid+1,r);
}
int update(int pre,int l,int r,int pos,int k){
int now=++tot,mid=(l+r)>>1;
if(l==r) {sum[now]=sum[pre]+k; return now;}
if(pos<=mid) rs[now]=rs[pre],ls[now]=update(ls[pre],l,mid,pos,k);
else ls[now]=ls[pre],rs[now]=update(rs[pre],mid+1,r,pos,k);
sum[now]=sum[ls[now]]+sum[rs[now]];
return now;
}
int query(int x,int y,int lca,int F,int l,int r,int L,int R){
if(L>R) return 0;
if(L==l && r==R) return sum[x]+sum[y]-sum[lca]-sum[F];
int mid=(l+r)>>1;
if(R<=mid) return query(ls[x],ls[y],ls[lca],ls[F],l,mid,L,R);
else if(L>mid) return query(rs[x],rs[y],rs[lca],rs[F],mid+1,r,L,R);
else return query(ls[x],ls[y],ls[lca],ls[F],l,mid,L,mid)+query(rs[x],rs[y],rs[lca],rs[F],mid+1,r,mid+1,R);
}
int ask(int x,int l,int r,int L,int R){
if(L<=l && r<=R) return sum[x];
int mid=(l+r)>>1,ret=0;
if(L<=mid) ret+=ask(ls[x],l,mid,L,R);
if(mid<R) ret+=ask(rs[x],mid+1,r,L,R);
return ret;
}
}tree; inline void add(int bg,int ed){
to[++cnt]=ed,nxt[cnt]=head[bg],head[bg]=cnt;
} void dfs(int x,int F){
in[x]=++num; fa[x]=F; siz[x]=1; int maxson=-1;
for(int i=head[x];i;i=nxt[i]){
int u=to[i]; if(u==F) continue;
dep[u]=dep[x]+1; dfs(u,x);
siz[x]+=siz[u];
if(siz[u]>maxson) maxson=siz[u],son[x]=u;
}
out[x]=++num;
} void dfs2(int x,int F){
rt[x]=rt[F];
for(int i=0;i<v[x].size();i++) {
rt[x]=tree.update(rt[x],1,2*n,in[v[x][i]],1);
rt[x]=tree.update(rt[x],1,2*n,out[v[x][i]],-1);
}
for(int i=head[x];i;i=nxt[i]){
int u=to[i]; if(u==F) continue;
dfs2(u,x);
}
} void dfs3(int x,int topf){
top[x]=topf; if(!son[x]) return;
dfs3(son[x],topf);
for(int i=head[x];i;i=nxt[i]){
int u=to[i]; if(u==fa[x] || u==son[x]) continue;
dfs3(u,u);
}
} inline int LCA(int x,int y){
while(top[x]!=top[y]){
if(dep[top[x]]>=dep[top[y]]) x=fa[top[x]];
else y=fa[top[y]];
}
return dep[x]>dep[y]?y:x;
} int main(){
n=rd(),m=rd(); int x,y,lca;
for(register int i=1;i<n;i++){
x=rd(),y=rd();
add(x,y),add(y,x);
}
for(register int i=1;i<=m;i++){
x=rd(),y=rd();
xx[i]=x,yy[i]=y;
v[x].push_back(y);
} dep[1]=1;
dfs(1,0); dfs2(1,0); dfs3(1,1);
for(register int i=1;i<=m;i++){
x=xx[i],y=yy[i],lca=LCA(x,y);
ans+=tree.query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,2*n,in[lca],in[x]);
ans+=tree.query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,2*n,in[lca],in[y]);
ans-=tree.query(rt[x],rt[y],rt[lca],rt[fa[lca]],1,2*n,in[lca],in[lca]);
ans--;
}
sum=(LL)m*(m-1)/2; LL GCD=__gcd(ans,sum);
printf("%lld/%lld\n",ans/GCD,sum/GCD);
return 0;
}

BZOJ 3772: 精神污染(dfs序+主席树)的更多相关文章

  1. 【BZOJ3772】精神污染 DFS序+主席树

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

  2. bzoj3772 精神污染 dfs 序+主席树

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=3772 题解 很简单的一道题目. 上午研究一个题目的时候发现了这个题目是一个弱化版,所以来写了一 ...

  3. BZOJ 3772: 精神污染 (dfs序+树状数组)

    跟 BZOJ 4009: [HNOI2015]接水果一样- CODE #include <set> #include <queue> #include <cctype&g ...

  4. bzoj 3653: 谈笑风生【dfs序+主席树】

    考虑b的两种情况,一种是p的祖先,这种点有min(k,de[p]-1)个,然后每个这种b都有si[p]-1个c点可选: 另一种是p的子孙,要求是在p的子树内且deep在de[p]+1~de[p]+k之 ...

  5. dfs序+主席树 或者 树链剖分+主席树(没写) 或者 线段树套线段树 或者 线段树套splay 或者 线段树套树状数组 bzoj 4448

    4448: [Scoi2015]情报传递 Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 588  Solved: 308[Submit][Status ...

  6. 2018.09.30 bzoj3551:Peaks加强版(dfs序+主席树+倍增+kruskal重构树)

    传送门 一道考察比较全面的题. 这道题又用到了熟悉的kruskal+倍增来查找询问区间的方法. 查到询问的子树之后就可以用dfs序+主席树统计答案了. 代码: #include<bits/std ...

  7. 【bzoj3545/bzoj3551】[ONTAK2010]Peaks/加强版 Kruskal+树上倍增+Dfs序+主席树

    bzoj3545 题目描述 在Bytemountains有N座山峰,每座山峰有他的高度h_i.有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询 ...

  8. 【bzoj1803】Spoj1487 Query on a tree III DFS序+主席树

    题目描述 You are given a node-labeled rooted tree with n nodes. Define the query (x, k): Find the node w ...

  9. bzoj 3772 :精神污染 线段树+打标记 or 主席树

    3772: 精神污染 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 315  Solved: 87[Submit][Status][Discuss] D ...

随机推荐

  1. windows10上使用一个tomcat部署2个项目

    前言:目前想在本机部署2个项目,网上查了之后,写下本篇随笔 1.准备工作 2.操作方法 3.运行2个项目 1.准备工作 2个war包(一个jprss.war和一个jenkins.war) 1个tomc ...

  2. Django 的工作流程和基本内容

    1.一个基本的Django请求流程 我们先开始写一个基本的请求.这个请求的获取和处理,是使用 urls.py 和 views.py 处理的.我们使用命令 python manage.py runser ...

  3. Selenium WebDriver高级应用

    WebDriver高级应用 public class Demo4 { WebDriver driver; // @BeforeMethod:在每个测试方法开始运行前执行 @BeforeMethod p ...

  4. Vagrant 入门 - 同步目录(synced folders)

    原文地址 尽管可以非常轻松的启动一台虚拟机,但很少有人希望通过 SSH 使用基于终端的编辑器来编辑文件.幸运的是,借助 Vagrant 你不需要这样做.通过使用同步目录,Vagrant 会自动同步 g ...

  5. [BZOJ2138]stone(Hall定理,线段树)

    Description 话说Nan在海边等人,预计还要等上M分钟.为了打发时间,他玩起了石子.Nan搬来了N堆石子,编号为1到N,每堆 包含Ai颗石子.每1分钟,Nan会在编号在\([L_i,R_i] ...

  6. 线程休眠只会用 Thread.sleep?来,教你新姿势!

    线程休眠是 Java 开发经常会用到的一个手段,就是让当前线程睡一会儿,睡醒之后再继续运行. 咱大多数程序员,多线程虽然学得不好,但线程休眠,无人不知,无人不晓,也都会用,不就是用 Thread.sl ...

  7. 牛逼哄哄的 API 网关是什么鬼?面试必问!

    Java技术栈 www.javastack.cn 优秀的Java技术公众号 作者:aCoder2013 github.com/aCoder2013/blog/issues/35 前言 假设你正在开发一 ...

  8. Codeforces 1148C(思维)

    题面 给出一个长度为n的排列a,每次可以交换序列的第i个和第j个元素,当且仅当\(2 \times |i-j| \geq n\),求一种交换方案,让序列从小到大排好序 分析 重点是考虑我们怎么把第x个 ...

  9. A Bug’s Life POJ - 2492(种类并查集)

    题目链接 每次给出两个昆虫的关系(异性关系),然后发现这些条件中是否有悖论 就比如说第一组数据 1 2 2 3 1 3 1和2是异性,2和3是异性,然后说1和3是异性就显然不对了. 我们同样可以思考一 ...

  10. sig文件制作

    一 配置环境变量 将link.exe,pcf.exe,sigmake.exe添加进PATH环境变量(选择“我的电脑” >“属性”>“高级” >“环境变量”>将文件地址添加进“p ...