PoPoQQQ的题解太神了,表示看了好久才看懂,于是自己写了一份题解祸害人类。

首先有一个结论对于一条路径x-->y,如果它的两个端点x和y都在另一条路径上,则这条路径被另一条路径包含。
    那么问题转化为了对于一条路径,判断两个端点都在这条路径上的路径有多少条。
    那么对于每一个节点x,我们用一个vector来存节点y,当且仅当存在一条路径x-->y。
    我们说主席树相当于前缀和S,那么我们现在要维护的序列A(即要维护前缀和的序列)表示什么呢?
    在主席树中每一个节点的A都是一个序列,序列的下标表示的是每个节点的入栈序和出栈序,那么我们对于每一个节点x,将它的vector中的y节点的入栈序和出栈序在它的A序列中+1和-1,那么我们看一下,假设有路径x-->y,又有路径x-->z,那么后者包含前者时,y的入栈序一定在z的入栈序和出栈序之间,y的出栈序一定在z的出栈序之后,那么我们查询的时候就可以直接查询z的入出栈序之间的权值和,即为有多少条一端是x节点的路径被路径x-->z包含。
    那么在树上建主席树,主席树的前缀和S就可以表示从根节点到这个节点x的路径上的A序列的和,那么查询时我们查询权值(下标)在lca(x,y)与y的入栈序之间的数的个数就是查询起点在根节点到x的路径上的终点在lca(x,y)与y之间的路径的个数。
    那么被路径x-->y包含的路径数目就是,记z为lca(x,y),
    ans=query(in[x])+query(in[y])-query(in[z])-query(in[fa[z]])-1
    其中query操作是在第x棵、第y棵、第z棵、第fa[z]棵中找权值(下标)在1-k之间的数的和,这四颗树可以提前提取出来,最后的-1是把自己给减去。
    最后要处理一下相同路径的问题。

然后并不知道为什么我直接询问前缀和会出错,但是如果区间查询的话就没有问题,这道题因为把4棵树提取出来还要写区间查询太麻烦了,所以直接放在函数里了。(原来可以区间查询呀,貌似跟普通的线段树一样呢)

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#define maxn 100010
#define maxm 4000010using namespace std;struct yts
{int x,y;
}q[maxn];int lch[maxm],rch[maxm],cnt[maxm];
int to[2*maxn],next[2*maxn],head[maxn],root[maxn];
int in[maxn],out[maxn],c[5];
int dep[maxn],fa[maxn][20];
int n,m,tot,num,num1;
vector<int> b[maxn];long long gcd(long long a,long long b)
{if (b==0) return a;else return gcd(b,a%b);
}void addedge(int x,int y)
{num++;to[num]=y;next[num]=head[x];head[x]=num;
}void dfs(int x)
{in[x]=++num1;for (int p=head[x];p;p=next[p])if (to[p]!=fa[x][0]){fa[to[p]][0]=x;dep[to[p]]=dep[x]+1;dfs(to[p]);}out[x]=++num1;
}int modify(int pre,int l,int r,int x,int f)
{int now=++tot;if (l==r){cnt[now]=cnt[pre]+f;lch[now]=rch[now]=0;}else{int mid=(l+r)/2;if (x<=mid){rch[now]=rch[pre];lch[now]=modify(lch[pre],l,mid,x,f);}else{lch[now]=lch[pre];rch[now]=modify(rch[pre],mid+1,r,x,f);}cnt[now]=cnt[lch[now]]+cnt[rch[now]];}return now;
}int query(int root1,int root2,int root3,int root4,int l,int r,int x,int y)
{if (l==x && y==r) return cnt[root1]+cnt[root2]-cnt[root3]-cnt[root4];int mid=(l+r)/2;if (y<=mid) return query(lch[root1],lch[root2],lch[root3],lch[root4],l,mid,x,y);if (mid<x) return query(rch[root1],rch[root2],rch[root3],rch[root4],mid+1,r,x,y);return query(lch[root1],lch[root2],lch[root3],lch[root4],l,mid,x,mid)+query(rch[root1],rch[root2],rch[root3],rch[root4],mid+1,r,mid+1,y);
}void dfs1(int x)
{root[x]=root[fa[x][0]];for (int i=0;i<b[x].size();i++){root[x]=modify(root[x],1,2*n,in[b[x][i]],1);root[x]=modify(root[x],1,2*n,out[b[x][i]],-1);}for (int p=head[x];p;p=next[p])if (to[p]!=fa[x][0])dfs1(to[p]);
}int go_up(int x,int d)
{for (int i=19;i>=0;i--)if (d&(1<<i)) x=fa[x][i];return x;
}int LCA(int x,int y)
{if (dep[x]>dep[y]) x=go_up(x,dep[x]-dep[y]);else y=go_up(y,dep[y]-dep[x]);if (x==y) return x;for (int i=19;i>=0;i--)if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];return fa[x][0];
}bool cmp(yts a,yts b)
{return a.x<b.x || (a.x==b.x && a.y<b.y);
}int main()
{scanf("%d%d",&n,&m);for (int i=1;i<n;i++){int x,y;scanf("%d%d",&x,&y);addedge(x,y);addedge(y,x);}for (int i=1;i<=m;i++){scanf("%d%d",&q[i].x,&q[i].y);b[q[i].x].push_back(q[i].y);}dep[1]=0;fa[1][0]=0;dfs(1);for (int j=1;j<=19;j++)for (int i=1;i<=n;i++)if (fa[i][j-1]) fa[i][j]=fa[fa[i][j-1]][j-1];else fa[i][j]=0;long long ans=0;tot=0;root[0]=lch[0]=rch[0]=cnt[0]=0;dfs1(1);for (int i=1;i<=m;i++){int x=q[i].x,y=q[i].y,z=LCA(x,y);ans+=query(root[x],root[y],root[z],root[fa[z][0]],1,2*n,in[z],in[x]);ans+=query(root[x],root[y],root[z],root[fa[z][0]],1,2*n,in[z],in[y]);ans-=query(root[x],root[y],root[z],root[fa[z][0]],1,2*n,in[z],in[z]);ans--;}sort(q+1,q+m+1,cmp);int j;for (int i=1;i<=m;i=j){for (j=i+1;j<=m && q[j].x==q[i].x && q[j].y==q[i].y;j++);ans-=(long long)(j-i)*(j-i-1)/2;}long long b=(long long)m*(m-1)/2,Gcd=gcd(ans,b);printf("%lld/%lld\n",ans/Gcd,b/Gcd);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. 双代号网络图节点编号原则_『干货』二级建造师考试高频考点 双代号网络图的详细解析...
  2. html网页钩子,HTML5中的meta标签 和 IE浏览器能识别的钩子
  3. 【嵌入式】Libmodbus之RTU模式Master端程序示例
  4. 教你玩转CSS 尺寸 (Dimension)
  5. html5是未来,开始用吧!
  6. WinForm中导出Excel
  7. mysql innodb 数据恢复_MYSQL INNODB 数据库恢复 转
  8. python连接不上数据库_详解pycharm连接不上mysql数据库的解决办法
  9. 自学stm32的一些个人经验
  10. 【Qt教程】3.2 - Qt5 event事件、定时器timerEvent
  11. 企业CRM项目实施调研内容有那些?
  12. 吴恩达教授机器学习课程笔记【六】- Part 6 学习理论
  13. 测试手机屏幕颜色软件,【AVW分享】一款你可以拥有的手机屏幕测试app
  14. java修改硬盘序列号怎么查_硬盘序列号的查看方法,如果多块硬盘如何查是哪块块的哪块要换掉?...
  15. 计算机科学美国大学专业,最新!2019年USNews美国大学计算机专业排名
  16. 《HTML CSS JavaScript 网页制作》第六章-创建框架结构网页
  17. Ubuntu+Tesla M40上OpenCL问题解决过程
  18. EJB:First component in name xxx not found - Java / Java EE
  19. VMware虚拟机去虚拟化完整版教程|永久过强壳VMP、SE壳、GK盾、TMD教程|VMware去虚拟化吾爱汇编论坛教程完整版
  20. 微信小程序---验证码倒计时

热门文章

  1. 测试手机软件打开速度的app,一加6千分之一秒 百款APP打开速度对比
  2. 暴雪战网怎么修改服务器,战网昵称修改服务
  3. [计算机网络]计算机网络发展历程,osi7层模型,报文交换
  4. 解释外显子,内含子,CDS、cDNA、EST、mRNA、ORF间的区别
  5. DOORS8.0的安装和基本使用
  6. 如何让溢出的文字省略号显示
  7. 百度AI—人脸在线比对
  8. 概率论与数理统计期末考试复习总结
  9. gephi和python_介绍用Gephi进行数据可视化
  10. 推荐系统----2020会议文章集锦