Hdu 4916 Count on the path
意甲冠军:鉴于一棵树的顶点标签为连续1~n,不是每个网上查询a-b最小的圆点标签路径
这题想了好久,如果1为根节点。
首先如果a-b只是根节点1。答案一定是1。
否则我们用fa[i]表示i节点的父亲,belong[i]表示i节点祖先是belong[i],且belong[i]是根节点儿子。这样我们能够预处理出ans[i]表示在belong[i]这颗子树中除去i到根节点的路径中最小的值。统计答案就可以。
讨论时需注意一些细节,首先处理出每一个节点的最小值和次小值,分别来源于它的两个子树。不包含节点本身。统计ans[i]的时候要在belong[i]中讨论且先统计不包含i本身子树的部分,显然ans[i]能够等于ans[fa[i]]。假设以i的子树(包含节点)的最小值和fa[i]的最小值相等,显然ans[i]能够等于fa[i]的次小值,由于i和fa[i]次小值节点不在一颗子树上;假设以i的子树(包含节点)的最小值和fa[i]的次小值相等,显然ans[i]能够等于fa[i]的最小值。最后再比較ans[i]和i本身子树最小值来更新ans[i]。
统计出ans[i]后每次询问O(1)回答就可以。
代码https://github.com/mlz000/hdu/blob/master/4916(%E6%A0%91%E4%B8%8A%E5%A5%BD%E9%A2%98).cpp
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=1000005,inf=1e9;
int n,q,tot,min3,belong[N],Q[N],head[N],next[N<<1],to[N<<1],fa[N],ans[N];
pair<int,int>a[N];
#define mp make_pair
void add(int u,int v){to[++tot]=v;next[tot]=head[u];head[u]=tot;
}
int ask(int x,int y){if(x>y) swap(x,y);if(x==1 || y==1){if(x==1 && y==1) return a[1].first;if(min(belong[y],ans[belong[y]])!=a[1].first) return a[1].first;return min(a[1].second,ans[y]);}else{if(belong[x]==belong[y]) return 1;int tmp1=min(belong[x],a[belong[x]].first),tmp2=min(belong[y],a[belong[y]].first);if(min(tmp1,tmp2)!=a[1].first) return a[1].first;int now=0;if(tmp1!=a[1].second && tmp2!=a[1].second) now=a[1].second;else now=min3;now=min(now,min(ans[x],ans[y]));return now;}
}
int main(){while(~scanf("%d%d",&n,&q)){int last=0;tot=0;memset(head,0,sizeof(head));for(int i=1,x,y;i<n;++i){scanf("%d%d",&x,&y);add(x,y);add(y,x);}Q[1]=1;for(int h=1,r=1;h<=r;++h){int now=Q[h];for(int i=head[now];i;i=next[i]){if(to[i]==fa[now]) continue;if(belong[now]) belong[to[i]]=belong[now];else belong[to[i]]=to[i];fa[to[i]]=now;Q[++r]=to[i];}}for(int i=1;i<=n;++i) a[i]=mp(inf,inf);for(int i=n;i>=1;--i){int now=Q[i];int tmp=min(now,a[now].first);int father=fa[now];if(tmp<a[father].second){a[father].second=tmp;if(a[father].second<a[father].first) swap(a[father].first,a[father].second);}}min3=inf;for(int i=head[1];i;i=next[i]){int now=min(to[i],a[to[i]].first);if(now!=a[1].first && now!=a[1].second) min3=min(min3,now);}for(int i=2;i<=n;++i){int minnow=min(Q[i],a[Q[i]].first);int father=fa[Q[i]];if(father!=1){ans[Q[i]]=ans[father];if(minnow==a[father].first) ans[Q[i]]=min(ans[Q[i]],a[father].second);else ans[Q[i]]=min(ans[Q[i]],a[father].first);}else ans[Q[i]]=inf;}for(int i=2;i<=n;++i) ans[i]=min(ans[i],a[i].first);while(q--){int x,y;scanf("%d%d",&x,&y);x=x^last;y=y^last;last=ask(x,y);printf("%d\n",last);}}return 0;
}
版权声明:本文博客原创文章。博客,未经同意,不得转载。
Hdu 4916 Count on the path相关推荐
- HDU 3336 Count the string(KMP+DP)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3336 题意:给你一个字符串,计算其所有前缀在该字符串出现的次数的总和. 思路:next[j]=i,代表 ...
- HDU 3336 Count the string KMP
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3336 如果你是ACMer,那么请点击看下 题意:求每一个的前缀在母串中出现次数的总和. AC代码: # ...
- HDU 4588 Count The Carries 数学
Count The Carries Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest ...
- HDU 5528 Count a * b
Count a * b 推式子 f(n)=∑i=0n−1∑j=0n−1n∤ij=n2−∑i=1n∑j=1nn∣ij=n2−∑i=1n∑j=1nngcd(i,n)∣igcd(i,n)j=n2−∑i=1n ...
- hdu 4472 Count(递推即dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4472 代码: #include <cstdio> #include <cstring ...
- 【HDU - 5492】Find a path(dp,tricks)
题干: Frog fell into a maze. This maze is a rectangle containing NN rows and MM columns. Each grid in ...
- 【HDU - 5883】The Best Path(判断欧拉回路)
题干: Alice is planning her travel route in a beautiful valley. In this valley, there are NN lakes, an ...
- HDU - 6016 Count the Sheep(二分图+思维)
题目链接:点击查看 题目大意:给出左右两个子集分别,再给出k条边,问能否找出四个点,让其连成一条路径 题目分析:一开始看到这个题肯定是个二分图,又因为有边,我就往度数上面想,一看四个点,就在想能不能枚 ...
- HDU - 3538 A sample Hamilton path(最短哈密顿路径+状压dp)
题目链接:点击查看 题目大意:求从0开始的最短哈密顿路径,并且要求了某些点的先后顺序 题目分析:哈密顿路径:由指定的起点前往指定的终点,途中经过所有其他节点且只经过一次(百度百科) 既然按照一定的次序 ...
最新文章
- pandas计算滑动窗口中的数值总和实战(Rolling Sum of a Pandas Column):计算单数据列滑动窗口中的数值总和(sum)、计算多数据列滑动窗口中的数值总和(sum)
- python使用sklearn的ConfusionMatrixDisplay来可视化混淆矩阵
- 关于VC++控制台输出中文乱码的问题
- camx模型_【推荐】基于CAMx的空气质量模拟及污染来源解析技术
- 开源一些Delphi系统:mp3play
- python基于rsa的数字签名实现_青岛宽客聚会期权定价公式基于python的实现
- ruby mysql dbi_Ruby MySQL DBI实例
- mysql format 格式化 返回值
- C语言带参数的main()函数
- java调用支付宝接口代码介绍
- 如何修改linux的 系统语言
- figure函数--Matplotlib
- Linux常用命令汇总及示例
- 怎么把PDF转换成Word格式?
- 暑假旺季到了,如何选择酒店呢
- 前端开发实习面试题(Vue篇)
- 计算机职业资格证书如何在网上查询?
- Jmeter性能测试脚本实战
- 分数阶傅立叶变换 matlab,【综述】分数阶傅里叶变换(FRFT)
- UTF-8编码的原理