题目描述

传送门

题解

对于每一条链计算能完全覆盖它的有多少条。
处理出来dfs序了之后,可以发现边大概分为三种情况:x和y的lca不是x和y中的某一个,x和y的lca是x或y,还有就是一条路径就是一个点。对于第一种情况,能覆盖它的路径一定是一个端点在x的子树里,一个端点在y的子树里。对于第二种情况,能覆盖它的路径一定是一个端点在y的子树里,另外一个端点在x的子树外。对于第三种情况,除了计算和第二种情况相似的之外,还要计算有多少条路径的lca是这个点,也就是覆盖了这个点。
用权值线段树套权值线段树即可,内层用动态开点,那么空间和时间都是O(nlogn)O(nlogn)。外层表示路径端点较小的dfs序,内层表示路径端点较大的dfs序。

刚开始竟然手残把lca写错了,gg。

代码

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define LL long long
#define N 100005
#define sz 17int n,m,x,y,dfs_clock,last,size,rest;
struct hp{int x,y,r,last;}e[N];
int tot,point[N],nxt[N*2],v[N*2];
int h[N],in[N],out[N],root[N],f[N][sz+3],cnt[N];
LL sum[N*20];int ls[N*20],rs[N*20];
LL up,down;int cmp(hp a,hp b)
{return in[a.x]<in[b.x]||(in[a.x]==in[b.x]&&in[a.y]<in[b.y]);
}
void add(int x,int y)
{++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
}
void dfs(int x,int fa)
{in[x]=++dfs_clock;h[x]=h[fa]+1;for (int i=1;i<sz;++i){if (h[x]-(1<<i)<1) break;f[x][i]=f[f[x][i-1]][i-1];}for (int i=point[x];i;i=nxt[i])if (v[i]!=fa){f[v[i]][0]=x;dfs(v[i],x);}out[x]=dfs_clock;
}
int lca(int x,int y)
{if (x==y) {last=x;return x;}if (h[x]<h[y]) swap(x,y);for (int i=sz-1;i>=0;--i)while (h[f[x][i]]>h[y])x=f[x][i];last=x;if (h[x]>h[y]) x=f[x][0];if (x==y) return x;for (int i=sz;i>=0;--i)if (f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];return f[x][0];
}
void update(int &now,int l,int r,int x)
{int mid=(l+r)>>1;sum[++size]=sum[now]+1,ls[size]=ls[now],rs[size]=rs[now];now=size;if (l==r) return;if (x<=mid) update(ls[now],l,mid,x);else update(rs[now],mid+1,r,x);
}
LL query(int now,int l,int r,int lrange,int rrange)
{int mid=(l+r)>>1;LL ans=0;if (lrange<=l&&r<=rrange) return sum[now];if (lrange<=mid) ans+=query(ls[now],l,mid,lrange,rrange);if (mid+1<=rrange) ans+=query(rs[now],mid+1,r,lrange,rrange);return ans;
}
LL gcd(LL a,LL b)
{if (!b) return a;else return gcd(b,a%b);
}int main()
{scanf("%d%d",&n,&m);for (int i=1;i<n;++i){scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);for (int i=1;i<=m;++i){scanf("%d%d",&x,&y);if (in[x]>in[y]) swap(x,y);e[i].x=x,e[i].y=y;e[i].r=lca(x,y);cnt[e[i].r]++;e[i].last=last;}sort(e+1,e+m+1,cmp);for (int i=1;i<=m;++i){if (i!=1&&in[e[i-1].x]!=in[e[i].x]-1)for (int j=in[e[i-1].x]+1;j<in[e[i].x];++j) root[j]=root[j-1];root[in[e[i].x]]=root[in[e[i-1].x]];update(root[in[e[i].x]],1,n,in[e[i].y]);}for (int i=in[e[m].x]+1;i<=n;++i) root[i]=root[i-1];for (int i=1;i<=m;++i){int r=e[i].r;last=e[i].last;if (r==e[i].x){   if (e[i].x!=e[i].y){int a=1,b=in[last]-1,c=in[e[i].y],d=out[e[i].y];if (a<=b)up+=query(root[b],1,n,c,d)-query(root[a-1],1,n,c,d);a=in[e[i].y],b=out[e[i].y],c=out[last]+1;d=n;if (c<=d)up+=query(root[b],1,n,c,d)-query(root[a-1],1,n,c,d);}else{int a=1,b=in[last]-1,c=in[last],d=out[last];if (a<=b)up+=query(root[b],1,n,c,d)-query(root[a-1],1,n,c,d);a=in[last],b=out[last],c=out[last]+1,d=n;if (c<=d)up+=query(root[b],1,n,c,d)-query(root[a-1],1,n,c,d);up+=(LL)cnt[last];}}else{int a=in[e[i].x],b=out[e[i].x],c=in[e[i].y],d=out[e[i].y];up+=query(root[b],1,n,c,d)-query(root[a-1],1,n,c,d);}}up-=m;down=(LL)m*((LL)m-1)/2;LL t=gcd(up,down);up/=t,down/=t;printf("%lld/%lld\n",up,down);return 0;
}

总结

一定要注意写主席树的时候要保证每一个点都有根(即使是光继承上一个),否则的话很可能减出负数来。

[BZOJ3772]精神污染(dfs序+主席树)相关推荐

  1. 洛谷 - P3899 [湖南集训]谈笑风生(dfs序+主席树/二维数点)

    题目链接:点击查看 题目大意:设 TTT 为一棵有根树,我们做如下的定义: 设 aaa 和 bbb 为 TTT 中的两个不同节点.如果 aaa 是 bbb 的祖先,那么称"aaa 比 bbb ...

  2. 洛谷 - P4197 Peaks(Kruskal重构树+dfs序+主席树)

    题目链接:点击查看 题目大意:有 n 座山峰,每座山峰有他的高度 h[ i ] ,有些山峰之间有双向道路相连,共 m 条路径,每条路径有一个困难值,这个值越大表示越难走. 现在有 q 组询问,每组询问 ...

  3. nowcoder172C 保护 (倍增lca+dfs序+主席树)

    https://www.nowcoder.com/acm/contest/172/C (sbw大佬太强啦 orz) 先把每一个路径(x,y)分成(x,lca),(y,lca)两个路径,然后就能发现,对 ...

  4. 【BZOJ3439】Kpm的MC密码,trie树+dfs序+主席树

    Time:2016.05.07 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 1.have a trie,还得是倒着建的,记录每个结尾节点的id(可能会有重复,所以开一个vecto ...

  5. 2021牛客多校7 - xay loves trees(dfs序+主席树-标记永久化)

    题目链接:点击查看 题目大意:给出两棵以点 111 为根节点的有根树,现在要求满足条件的最大集合: 在第一棵树中,集合内的任意两个点都必须满足祖先关系,即 uuu 是 vvv 的祖先或 vvv 是 u ...

  6. 2021牛客暑期多校训练营7 xay loves trees dfs序 + 主席树

    传送门 文章目录 题意: 思路: 题意: 给你两棵树,让你在第一棵树选一条最长的深度递增的链,链上每一个点在第二棵树上都不互为祖先. n≤3e5n\le3e5n≤3e5 思路: 之前做过差不多的题传送 ...

  7. [BZOJ3772]精神污染

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

  8. New Year Tree(dfs序+线段树+二进制)

    题意: 给出一棵 n个节点的树,根节点为 1.每个节点上有一种颜色 ci.m次操作.操作有两种: 1 u c:将以 u为根的子树上的所有节点的颜色改为c. 2 u:询问以 u为根的子树上的所有节点的颜 ...

  9. 求和(dfs序+线段树)

    题意: 已知有n个节点,有n−1条边,形成一个树的结构. 给定一个根节点k,每个节点都有一个权值,节点i的权值为vi​. 给m个操作,操作有两种类型: 1 a x :表示将节点a的权值加上x 2 a ...

  10. 【XSY2667】摧毁图状树 贪心 堆 DFS序 线段树

    题目大意 给你一棵有根树,有\(n\)个点.还有一个参数\(k\).你每次要删除一条长度为\(k\)(\(k\)个点)的祖先-后代链,问你最少几次删完.现在有\(q\)个询问,每次给你一个\(k\), ...

最新文章

  1. Pandas 使用入门
  2. @程序员,第一批00后开始报考AI专业了
  3. Visual Stodio 2010 待熟悉技巧
  4. Nat.Mach.Intell.| DEcode:深度学习解读差异基因表达原理
  5. C++ 中 string earse 函数的使用
  6. 华为内部面试题库---(10)
  7. cepl进程 Linux,Ubuntu下NS2-2.33安装过程
  8. java中的双与_java 双冒号是什么操作符?
  9. java xml 读取库_Java开发中读取XML与properties配置文件的方法
  10. (五)自动化MLOps部署到Kubernetes
  11. mysql v$session_关于V$SESSION视图
  12. 深入理解ajax系列第九篇
  13. 多功能雨伞项目计划书_多功能的雨伞创业项目计划书
  14. win7系统修改磁盘提示参数错误的解决办法
  15. 基于Profibus-DP协议的PLC智能从站设计
  16. 剑指offer_递归与循环---变态跳台阶
  17. Emmet 食用指北
  18. 电位器的阻值曲线变化特性解析与应用
  19. 记一次Java代码不执行,也不报错!求大佬赐教!
  20. Android自定义View之Canvas绘制基本图形(二)-- 自定义时钟

热门文章

  1. 第九课堂-如何通过着装打造黄金比例完美好身材!
  2. 2022-02-09 Android setLayoutParams动态修改RelativeLayout控件layout_width、layout_marginTop等。实际应用实例:控件随手指移动。
  3. 云服务器防 DDoS 攻击的几种方法策略分享
  4. 在php中插入表格,word怎么插入表格
  5. 互金平台乘着东风股价反弹,小赢科技为何成上涨“急先锋”?
  6. python的并行计算框架
  7. CTSC2018 APIO2018 颓废 + 打铁记
  8. Request method XXX not supported
  9. Mac 系统更新系统安装包损坏丢失,崩溃
  10. URAL 1389 Roadworks 贪心