codeforces1486 F. Pairs of Paths(倍增+树上数数)

F. Pairs of Paths

syksykCCC题解
iamhpp题解
首先说明,下面图片来自第一篇博客,下面代码照抄第二篇博客
对没有啥是自己写的(因为我太菜~~
在这里插入图片描述
从上图可以看出两条链只有一个交点可能有两种情况

  • 交点是两条链的LCA
  • 交点是一条链的LCA而不是另一条

这两种情况的公共点就是:交点一定是一条链的LCA,因此我们从LCA考虑计数

对于第一种情况,如果存在一条链x0⇝y0x_0\leadsto y_0x0y0x⇝yx\leadsto yxy满足条件,一定有LCA(x0,y0)=LCA(x,y)LCA(x_0,y_0)=LCA(x,y)LCA(x0,y0)=LCA(x,y)并且x,y,x0,y0x,y,x_0,y_0x,y,x0,y0分别处在lcalcalca的4棵子树中。
首先每次考虑相同LCA的链,因而第一个条件满足,第二个条件我们每条链记录xxx处于lca的aaa子树中,而yyy处于lca的bbb子树中,也就是如果lca是xxxkkk级祖先,那么aaaxxxk−1k-1k1级祖先(倍增跳一下即可)链的情况,把aaa设为−1-11

有了上面信息,我们考虑一条链x⇝yx\leadsto yxy,那些和它LCA相同的链x0⇝y0x_0\leadsto y_0x0y0对答案有贡献当且仅当a,b,a0,b0a,b,a_0,b_0a,b,a0,b0是4个不同的值,这可以用容斥原理计算

对于第二种情况,对于上图考虑A1⇝A2A_1\leadsto A_2A1A2这条链存在多少条像B1⇝B2B_1\leadsto B_2B1B2的链,首先不难发现B1⇝B2B_1\leadsto B_2B1B2的LCA的深度一定严格小于A1⇝A2A_1\leadsto A_2A1A2的LCA,也就是如果想要和A1⇝A2A_1\leadsto A_2A1A2配对对答案产生贡献,那么其链的LCA深度一定较小,因此考虑按照LCA深度排序依次处理。

每次只需要统计LCA子树中有多少像B1B_1B1这样的点(在LCA的子树中并且A1,A2A_1,A_2A1,A2在同一子树)找个支持单点修改子树查询的数据结构即可,这里用dfs序+树状数组统计。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#pragma GCC optimize(2)
#include<map>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
using pii=pair<int,int>;
constexpr int N=300010;
int h[N],e[2*N],ne[2*N],idx;
void add(int a,int b){e[idx]=b,ne[idx]=h[a],h[a]=idx++;}
int n,m;
int dep[N],fa[N][21],dfn[N],sz[N],timestamp;
void dfs(int u)
{dfn[u]=++timestamp;sz[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa[u][0])continue;dep[v]=dep[u]+1;fa[v][0]=u;for(int k=1;k<=20;k++)fa[v][k]=fa[fa[v][k-1]][k-1];dfs(v);sz[u]+=sz[v];}
}
int lca(int u,int v)
{if(dep[u]<dep[v]) swap(u,v);for(int k=20;k>=0;k--)if(dep[fa[u][k]]>=dep[v]) u=fa[u][k];if(u==v) return u;for(int k=20;k>=0;k--)if(fa[u][k]!=fa[v][k]) u=fa[u][k],v=fa[v][k];return fa[u][0];
}
int up(int u,int d)// 从u向上跳d步
{if(d<=0) return u;for(int k=20;k>=0;k--)if(d>>k&1) u=fa[u][k];return u;
}
struct node
{int x,y,a,b,lca;
}q[N];
int fw[N];
int lowbit(int x){return x&-x;}
void update(int k,int x){for(;k<=n;k+=lowbit(k)) fw[k]+=x;}
int query(int k){int res=0;for(;k;k-=lowbit(k)) res+=fw[k];return res;}int main()
{IO;cin>>n;memset(h,-1,sizeof h);for(int i=1;i<n;i++){int u,v;cin>>u>>v;add(u,v),add(v,u);}dep[1]=1;dfs(1);cin>>m;for(int i=1;i<=m;i++){int x,y;cin>>x>>y;int anc=lca(x,y);int a=up(x,dep[x]-dep[anc]-1),b=up(y,dep[y]-dep[anc]-1);if(a==anc) a=-1;if(b==anc) b=-1;if(a>b) swap(a,b),swap(x,y);q[i]={x,y,a,b,anc};}sort(q+1,q+1+m,[](const node &i,const node&j){if(dep[i.lca]!=dep[j.lca]) return dep[i.lca]<dep[j.lca];return i.lca<j.lca;});ll ans1=0,ans2=0;for(int i=1;i<=m;i++){map<pii,int> f;map<int,int> cnt;int j=i;while(j<=m&&q[j].lca==q[i].lca) j++;//lca相同的一起统计for(int k=i;k<j;k++){int x=q[k].x,y=q[k].y,a=q[k].a,b=q[k].b,anc=q[k].lca;ans1+=k-i-cnt[a]-cnt[b]+f[{a,b}];if(a!=-1) cnt[a]++;if(b!=-1) cnt[b]++;if(a!=-1&&b!=-1) f[{a,b}]++;}i=j-1;}for(int i=1;i<=m;i++){int j=i;while(j<=m&&dep[q[j].lca]==dep[q[i].lca]) j++;//深度相同的一起统计for(int k=i;k<j;k++){int x=q[k].x,y=q[k].y,a=q[k].a,b=q[k].b,anc=q[k].lca;ans2+=query(dfn[anc]+sz[anc]-1)-query(dfn[anc]-1);if(a!=-1) ans2-=query(dfn[a]+sz[a]-1)-query(dfn[a]-1);if(b!=-1) ans2-=query(dfn[b]+sz[b]-1)-query(dfn[b]-1);}for(int k=i;k<j;k++) update(dfn[q[k].x],1),update(dfn[q[k].y],1);i=j-1;}cout<<ans1+ans2<<'\n';
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319025.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

学习Raft算法的笔记

Raft是一种为了管理日志复制的一致性算法。它提供了和Paxos算法相同的功能和性能&#xff0c;但是它的算法结构和Paxos不同&#xff0c;使得Raft算法更加容易理解并且更容易构建实际的系统。为了提升可理解性&#xff0c;Raft将一致性算法分解成几个关键的模块&#xff0c;例如…

P3335-[ZJOI2013]蚂蚁寻路【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P3335 题目大意 给出nmn\times mnm的网格&#xff0c;每个格子有权值。一个回路在格子的边上&#xff0c;要求有2k2\times k2k次左转&#xff0c;其他都是右转&#xff0c;且最后222次一定得是右转。 求包含的格子权值和最大…

牛客题霸 最少素数拆分 C++题解/答案

牛客题霸 最少素数拆分 C题解/答案 题目描述 牛牛刚刚学习了素数的定义&#xff0c;现在给定一个正整数N&#xff0c;牛牛希望知道N最少表示成多少个素数的和。 素数是指在大于1的自然数中&#xff0c;除了1和它本身以外不再有其他因数的自然数。 提示 哥德巴赫猜想&#xf…

LOJ dfs序1234

DFS 序 1 题目要求&#xff1a; ① uuu节点权值xxx ② 询问uuu子树权值和 uuu节点权值xxx &#xff1a;直接加uuu子树权值和&#xff1a;dfs序树状数组 LOJ提交代码 DFS 序 1 DFS 序 2 题目要求&#xff1a; ① uuu节点子树权值xxx ② 询问uuu子树权值和 uuu节点子树权值xxx&…

.NET Core 必备安全措施

.NET Core大大简化了.NET应用程序的开发。它的自动配置和启动依赖大大减少了开始一个应用所需的代码和配置量&#xff0c;本文目的是介绍如何创建更安全的.NET Core应用程序。1.在生产中使用HTTPS传输层安全性&#xff08;TLS&#xff09;是HTTPS的官方名称&#xff0c;你可能听…

CF1370F2-The Hidden Pair(Hard Version)【交互题,二分】

正题 题目链接:https://www.luogu.com.cn/problem/CF1370F2 题目大意 TTT组数据&#xff0c;给出nnn个点的一棵树&#xff0c;有两个隐藏的关键点。你每次可以询问一个点集&#xff0c;交互库会回答这个点集中的一个点满足它到两个关键点的距离和最小&#xff0c;和这个距离。…

牛客题霸题目及题解汇总

牛客题霸 单链表的选择排序 C题解/答案牛客题霸 最少素数拆分 C题解/答案牛客题霸 两数之和 C题解/答案牛客题霸 反转链表 C题解/答案牛客题霸 二分查找 C题解/答案牛客题霸 判断链表中是否有环 C题解/答案牛客题霸 转圈打印矩阵 C题解/答案牛客题霸 [斐波那契数列] C题解/答牛…

HDU5126 stars(4维偏序->cdq套cdq+树状数组)

stars 题目大意&#xff1a; 在一个三维空间当中&#xff0c;每次进行一个操作&#xff0c;添加一个点或者统计空间中的某一个长方体范围内的所有点 三维空间中我们用两个点即可确定一个长方体。 首先效仿平面二维数点的方法&#xff0c;根据容斥原理可以把询问拆分成8个以原点…

[翻译] C# 8.0 新特性

原文: Building C# 8.0[译注:原文主标题如此&#xff0c;但内容大部分为新特性介绍&#xff0c;所以意译标题为 "C# 8.0 新特性"]C# 的下一个主要版本是 8.0。我们已经为它工作了很长一段时间&#xff0c;即使我们构建并发布了次要版本 C# 7.1, 7.2 和 7.3&#xff0…

[蓝桥杯][2018年第九届真题]搭积木

[[蓝桥杯][2018年第九届真题]搭积木](https://www.dotcpp.com/oj/problem2292.html)题目&#xff1a; 小明对搭积木非常感兴趣。他的积木都是同样大小的正立方体。 在搭积木时&#xff0c;小明选取 m 块积木作为地基&#xff0c;将他们在桌子上一字排开&#xff0c;中间不留空…

NOI.AC#2007-light【根号分治】

正题 题目链接:http://noi.ac/problem/2007 题目大意 nnn个格子排成一排&#xff0c;每个格子有一个0/10/10/1和一个颜色。开始每个格子都是000&#xff0c;qqq次操作取反一个颜色的所有格子的0/10/10/1&#xff0c;然后询问111的格子构成的连通块数量。 1≤n,q≤1051\leq n,q…

【招聘(广州)】 招聘.NET程序员

招聘&#xff1a;.NET程序员工作地点&#xff1a;广州天河区CBD&#xff08;地铁3号线珠江新城站&#xff09;职位描述&#xff1a;网站平台、移动页面、APP、微信小程序、接口等开发&#xff1b;与UI/UX&#xff0c;设计师、产品经理偕同工作一起排查、定位、优化产品性能。任…

【模板】一维树状数组

ACM模板 目录聊聊前缀和什么是树状数组?树状数组相关操作局限性差分在树状数组中的应用区间更新、单点查询区间更新、区间查询树状数组应用聊聊前缀和 比如数组 int a[7]{1,2,3,4,5,6,7}如果需询问数组从第l个数到第r个数的和暴力做法时间复杂度为O(n)O(n)O(n) 不过我们可以…

牛客题霸 单链表的选择排序 C++题解/答案

牛客题霸 单链表的选择排序 C题解/答案 题目描述 给定一个无序单链表&#xff0c;实现单链表的选择排序(按升序排序)。 题解&#xff1a; 不可能手写排序&#xff0c;这辈子不可能手写排序。。 基础的链表操作&#xff0c;将链表内的数据存到vector内&#xff0c;然后用sor…

牛客练习赛71E-神奇的迷宫【点分治,NTT】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7745/E 题目大意 给出nnn个点的一棵树&#xff0c;每个点有一个选择权重aia_iai​&#xff08;有ai∑i1nai\frac{a_i}{\sum_{i1}^na_i}∑i1n​ai​ai​​的概率被选择&#xff09;。 然后有一个序列www。随机选择两次点&…

使用C#把Tensorflow训练的.pb文件用在生产环境

训练了很久的Tf模型&#xff0c;终于要到生产环境中去考验一番了。今天花费了一些时间去研究tf的模型如何在生产环境中去使用。大概整理了这些方法。继续使用分步骤保存了的ckpt文件这个貌似脱离不了tensorflow框架&#xff0c;而且生成的ckpt文件比较大&#xff0c;发布到生产…

OpenJudge1043 树上游戏(换根dp+细节处理)

树上游戏 给定一棵 nnn 个节点的树&#xff0c;点从 111 到 nnn 编号&#xff0c;点有点权&#xff0c;边有边权&#xff0c; Alice\text{Alice}Alice 和 Bob\text{Bob}Bob 两人在做游戏。 棋子以某一个点 sss 为起点&#xff0c;玩家移动该棋子&#xff0c;有以下两条规则&a…

牛客题霸 转圈打印矩阵 C++题解/答案

牛客题霸 转圈打印矩阵 C题解/答案 题目描述 给定一个整型矩阵matrix&#xff0c;请按照顺时针转圈的方式打印它。 示例1 输入 复制 [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] 返回值 复制 [1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10] 题解&#xff1a; 题意很明确…

【招聘(上海)】东方财富证券招聘.net开发

东方财富证券&#xff1a;东方财富网(深创&#xff1a;300059)旗牌照齐全证券公司&#xff0c;极具互联网基因的券商。.Net服务端开发工程师/.Net前端开发工程师[职位介绍]服务端&#xff1a;开户、交易及资讯系统的后端接口服务(Asp.Net WebApi)开发&#xff1b;服务端&#x…

2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7609/C 题目大意 给出nnn个点的一棵树&#xff0c;mmm个时刻各有一个操作 标记一个点&#xff0c;每个点被标记后的每一个时刻会标记掉周围的点。删去所有点的标记询问一个点是否有标记 解题思路 考虑没有二操作怎么搞&…