意甲冠军:鉴于一棵树的顶点标签为连续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相关推荐

  1. HDU 3336 Count the string(KMP+DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3336 题意:给你一个字符串,计算其所有前缀在该字符串出现的次数的总和. 思路:next[j]=i,代表 ...

  2. HDU 3336 Count the string KMP

    题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3336 如果你是ACMer,那么请点击看下 题意:求每一个的前缀在母串中出现次数的总和. AC代码: # ...

  3. HDU 4588 Count The Carries 数学

    Count The Carries Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest ...

  4. 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 ...

  5. hdu 4472 Count(递推即dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4472 代码: #include <cstdio> #include <cstring ...

  6. 【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 ...

  7. 【HDU - 5883】The Best Path(判断欧拉回路)

    题干: Alice is planning her travel route in a beautiful valley. In this valley, there are NN lakes, an ...

  8. HDU - 6016 Count the Sheep(二分图+思维)

    题目链接:点击查看 题目大意:给出左右两个子集分别,再给出k条边,问能否找出四个点,让其连成一条路径 题目分析:一开始看到这个题肯定是个二分图,又因为有边,我就往度数上面想,一看四个点,就在想能不能枚 ...

  9. HDU - 3538 A sample Hamilton path(最短哈密顿路径+状压dp)

    题目链接:点击查看 题目大意:求从0开始的最短哈密顿路径,并且要求了某些点的先后顺序 题目分析:哈密顿路径:由指定的起点前往指定的终点,途中经过所有其他节点且只经过一次(百度百科) 既然按照一定的次序 ...

最新文章

  1. pandas计算滑动窗口中的数值总和实战(Rolling Sum of a Pandas Column):计算单数据列滑动窗口中的数值总和(sum)、计算多数据列滑动窗口中的数值总和(sum)
  2. python使用sklearn的ConfusionMatrixDisplay来可视化混淆矩阵
  3. 关于VC++控制台输出中文乱码的问题
  4. camx模型_【推荐】基于CAMx的空气质量模拟及污染来源解析技术
  5. 开源一些Delphi系统:mp3play
  6. python基于rsa的数字签名实现_青岛宽客聚会期权定价公式基于python的实现
  7. ruby mysql dbi_Ruby MySQL DBI实例
  8. mysql format 格式化 返回值
  9. C语言带参数的main()函数
  10. java调用支付宝接口代码介绍
  11. 如何修改linux的 系统语言
  12. figure函数--Matplotlib
  13. Linux常用命令汇总及示例
  14. 怎么把PDF转换成Word格式?
  15. 暑假旺季到了,如何选择酒店呢
  16. 前端开发实习面试题(Vue篇)
  17. 计算机职业资格证书如何在网上查询?
  18. Jmeter性能测试脚本实战
  19. 分数阶傅立叶变换 matlab,【综述】分数阶傅里叶变换(FRFT)
  20. UTF-8编码的原理

热门文章

  1. matlab图像处理函数大全
  2. mysql基础命令大全
  3. 网络实验环境搭建--1.工具及搭建思路
  4. Go语言 模糊搜索实验(一)
  5. 牛客网——数字求和(水题
  6. P3978 [TJOI2015]概率论
  7. B - 一只小蜜蜂...
  8. 把tomcat默认的8080段口改成80端口
  9. select,poll,epoll用法
  10. php运算符的特殊用法