BZOJ[3772]精神污染

本题就是求每条路径被多少条路径所覆盖(也可以求覆盖了多少条路径)。

我们对于一条路径,分析怎样的路径可以覆盖它。

假设路径A的两个端点为x,y,路径B的两个端点为a,b。(Dfn[a]&lt;Dfn[b]andDfn[x]&lt;Dfn[y]Dfn[a]&lt;Dfn[b]\ and\ Dfn[x]&lt;Dfn[y]Dfn[a]<Dfn[b] and Dfn[x]<Dfn[y])(注意这里的大小关系)

Dfn[i]表示i的dfs序,Lst[i]表示i子树内dfs序最大的点的dfs序。

如果这条路径A不是一条直链(也就是一个点是另一个点的祖先),那么如果另一条路径B要想覆盖它,就得满足B的两个端点分别在A的两个端点的子树中。

那么Dfn[a]∈[Dfn[x],Lst[x]]andDfn[b]∈[Dfn[y],Lst[y]]Dfn[a]∈[Dfn[x],Lst[x]]\ and\ Dfn[b]∈[Dfn[y],Lst[y]]Dfn[a]∈[Dfn[x],Lst[x]] and Dfn[b]∈[Dfn[y],Lst[y]]

如果这条路径是一条直链,那么。。(难以描述,先看图)

假设这条路径就是X–Y,那么另一条路径的一个端点会在A这个集合中,另一个端点会在B这个集合里,也就是不在S的子树里。(S是X到Y路径上Y的儿子)。

所以Dfn[a]∈[1,Dfn[S]−1]andDfn[b]∈[Dfn[x],Lst[x]]Dfn[a]∈[1,Dfn[S]-1]\ and\ Dfn[b]∈[Dfn[x],Lst[x]]Dfn[a]∈[1,Dfn[S]−1] and Dfn[b]∈[Dfn[x],Lst[x]]或者是Dfn[a]∈[Dfn[x],Lst[x]]andDfn[b]∈[Lst[S]+1,n]Dfn[a]∈[Dfn[x],Lst[x]]\ and\ Dfn[b]∈[Lst[S]+1,n]Dfn[a]∈[Dfn[x],Lst[x]] and Dfn[b]∈[Lst[S]+1,n]

因为这里要使Dfn[a]&lt;Dfn[b]Dfn[a]&lt;Dfn[b]Dfn[a]<Dfn[b],故这个关系式才会长这样。

有了这两个关系式,本题就变成了一个二维数点问题,把每条路径看成(Dfn[x],Dfn[y])这样一个点,再用主席树什么的即可求解。(注意算的时候要把自己包含自己的情况删去)

AC代码:

#include<cstdio>
#include<algorithm>
#define M 100005
using namespace std;
struct E{int to,nx;
}edge[M<<1];
int tot,head[M];
void Addedge(int a,int b){//正向表 edge[++tot].to=b;edge[tot].nx=head[a];head[a]=tot;
}
int fa[M][20];
int Dfn[M],Lst[M],id_dfs;
struct Line{int x,y; bool operator <(const Line &_)const{//先按x的DFS序排序 if(Dfn[x]!=Dfn[_.x])return Dfn[x]<Dfn[_.x];return Dfn[y]<Dfn[_.y];}
}T[M];
int dep[M];
int Up(int x,int y){//找x的第y个父亲 if(y<0)return 0;//如果x是y的祖先 for(int i=0;i<20;i++)if((1<<i)&y)x=fa[x][i];return x;
}
void dfs(int now){Dfn[now]=++id_dfs;for(int i=1;i<20;i++)fa[now][i]=fa[fa[now][i-1]][i-1];for(int i=head[now];i;i=edge[i].nx){int nxt=edge[i].to;if(fa[now][0]==nxt)continue;dep[nxt]=dep[now]+1;fa[nxt][0]=now;dfs(nxt);}Lst[now]=id_dfs;
}
long long gcd(long long a,long long b){if(!b)return a;return gcd(b,a%b);
}
struct Chair_tree{//一颗主席树 int Root[M];int sum[M*20],Lson[M*20],Rson[M*20],tot;void clear(){tot=0;Root[0]=sum[0]=Lson[0]=Rson[0]=0;}void Updata(int L,int R,int x,int oid,int &tid){tid=++tot;sum[tid]=sum[oid]+1;Lson[tid]=Lson[oid];Rson[tid]=Rson[oid];if(L==R)return;int mid=(L+R)>>1;if(x<=mid)Updata(L,mid,x,Lson[oid],Lson[tid]);else Updata(mid+1,R,x,Rson[oid],Rson[tid]);}int Query(int L,int R,int Lx,int Rx,int Lid,int Rid){if(!Lid&&!Rid)return 0;if(Lx<=L&&R<=Rx)return sum[Rid]-sum[Lid];int mid=(L+R)>>1;if(Rx<=mid)return Query(L,mid,Lx,Rx,Lson[Lid],Lson[Rid]);if(Lx>mid)return Query(mid+1,R,Lx,Rx,Rson[Lid],Rson[Rid]);return Query(L,mid,Lx,mid,Lson[Lid],Lson[Rid])+Query(mid+1,R,mid+1,Rx,Rson[Lid],Rson[Rid]);}
}CT;
int main(){CT.clear();int n,m;scanf("%d%d",&n,&m);for(int i=1;i<n;i++){int a,b;scanf("%d%d",&a,&b);Addedge(a,b);Addedge(b,a);}long long ans=0,tot=1ll*m*(m-1)/2;dfs(1);for(int i=1;i<=m;i++){scanf("%d%d",&T[i].x,&T[i].y);if(Dfn[T[i].x]>Dfn[T[i].y])swap(T[i].x,T[i].y);//使x的DFS序大于y }sort(T+1,T+m+1);//按x的DFS序排序 for(int i=1,id=1;i<=n;i++){//往主席树里加点 CT.Root[i]=CT.Root[i-1];while(id<=m&&Dfn[T[id].x]<=i){CT.Updata(1,n,Dfn[T[id].y],CT.Root[i],CT.Root[i]);id++;}}for(int i=1;i<=m;i++){int x=T[i].x,y=T[i].y;//如果这是一条链,那么dep[x]<dep[y] int s=Up(y,dep[y]-dep[x]-1);//同题解里的图里的S if(fa[s][0]==x){//如果这是一条链 ans+=CT.Query(1,n,Dfn[y],Lst[y],CT.Root[0],CT.Root[Dfn[s]-1]);ans+=CT.Query(1,n,Lst[s]+1,n,CT.Root[Dfn[y]-1],CT.Root[Lst[y]]);ans--;//减去自己包含自己的情况 }else ans+=CT.Query(1,n,Dfn[y],Lst[y],CT.Root[Dfn[x]-1],CT.Root[Lst[x]])-1;}long long g=gcd(ans,tot);printf("%lld/%lld\n",ans/g,tot/g);return 0;
}

BZOJ[3772]精神污染 二维数点相关推荐

  1. 点分治 + 树状数组 ---- E. Close Vertices(点分治 + 二维数点)

    题目链接 题目大意: 给出一棵树,问有多少条路径权值和不大于www,长度不大于lll 解题思路: 首先树上路径问题大概率就是点分治了 但是我们对于每个路径有两个性质就是(li,wi)(l_i,w_i) ...

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

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

  3. 洛谷 - P2163 [SHOI2007]园丁的烦恼(不带修二维数点-树状数组/主席树)

    题目链接:点击查看 题目大意:二维平面坐标系中给出 nnn 个坐标点,然后是 mmm 次询问,每次询问需要回答一个闭合矩阵中有多少个点 题目分析:想挂树套树来着,但是复杂度有点大.本题不带修且可以离线 ...

  4. P3899 [湖南集训]谈笑风生 主席树解决二维数点

    传送门 文章目录 题意: 思路: 题意: 思路: 由于a,ba,ba,b都比ccc厉害,那么a,ba,ba,b一定是某个是某个的祖先.那么就分为两种情况了: (1)(1)(1) bbb在aaa上面,约 ...

  5. LG P4899 [IOI2018] werewolf 狼人(kruskal重构树,二维数点)

    LG P4899 [IOI2018] werewolf 狼人 Solution 我们发现010101限制长这样子: ∃x(minids−>x≥L&maxidx−>e≤R)→1\ex ...

  6. P2163 [SHOI2007]园丁的烦恼(二维数点模板题)

    P2163 [SHOI2007]园丁的烦恼 题意: 在一个二维平面内有一些点,给你一个左上角和右下角的点,问这个范围内有多少点 题解: 二维数点模板题 我们设F(a,b)表示以(0,0)为左下角,(a ...

  7. 【无码专区8】三角形二维数点——计数有多少个给定点落在三角形区域内

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...

  8. P3899 [湖南集训]更为厉害(线段树合并、长链剖分、二维数点)

    P3899 [湖南集训]更为厉害 若 deepb<deepa\text{deep}_b<\text{deep}_adeepb​<deepa​:c 在点 a 的子树中,根据乘法原理计算 ...

  9. F. Paper Grading(Trie树+dfs序+二维数点)

    F. Paper Grading 大佬题解 一般关于前缀的问题基本都是Trie树. 首先将所给字符串建立一棵Trie树,Trie能够解决一个字符串在一个字符串集合中出现的次数,而查询前缀次数只需要找到 ...

  10. 【一类题】二维数点的几个做法

    二维数点的题目还用赘述么-- 题意就是这道题 离线 $CDQ$ 分治 在线 $k-d tree$ 转载于:https://www.cnblogs.com/scx2015noip-as-php/p/tw ...

最新文章

  1. ORA-00907:缺少右括号
  2. linux下实现作业调度程序,Linux后台作业
  3. 12月27日云栖精选夜读:实人认证 - 阿里云实人认证(公测)发布
  4. jquery ui php,php – 打开带有动态内容的jQuery UI对话框
  5. mate7 刷机 android 7,Mate7 四大版本完整稳定版刷机包大集合!
  6. 使用遗传算法解决N皇后问题
  7. Linux中bond的七种网卡绑定模式详解
  8. LayaBox1.7.16 TiledMap 销毁的问题,TiledMap销毁后屏幕变灰,不能显示
  9. edge浏览器怎么设置activex_Edge浏览器ActiveX插件
  10. 北大计算机前辈徐,九年中获得国家最高科学技术奖的八位北大人
  11. 手推公式--马氏距离
  12. Windows 7各版本的主要功能区别是什么 有何不同
  13. seo需要编程技术吗?学黑帽seo需要什么技术?
  14. C# Linq 左外联
  15. 深度学习—利用TensorFlow2实现狗狗品种品种(DenseNet121实现)
  16. Flowable工作流引擎技术方案
  17. 312. 戳气球(区间dp)
  18. 华脉智联电力行业技术解决方案
  19. 山西省大学计算机专业排名,山西省:排名前14的大学!山西的大学分为5档,前2档最难考!...
  20. JAVA实现雪花飘落动画效果

热门文章

  1. PDF页码怎么设置?如何给PDF文件设置页码
  2. MySQL基础篇(上)
  3. 读入一系列正整数数据,输入-1表示输入结束,-1本身不是输入的数据。程序输出读到的数据中的奇数和偶数的个数。
  4. 应用之星破除行业门槛 零成本开发手机应用
  5. 个人微信公众号申请流程
  6. 前沿 | 社区问答系统及相关技术
  7. Push failed Remote: Support for password authentication was removed on August 13, 2021.
  8. 苹果平板历史各版本 援引自知乎https://www.zhihu.com/question/315944330
  9. [cryptoverse ctf 2022] cvctf
  10. wing ftp server网页无法访问