gym102201F_Fruit Tree
题意
给一棵带权树,多次询问路径上出现次数超过一半的数。
分析
- dfs序建主席树,维护的就是根到某个节点这段路径的值域情况。
- 因为题目所求的不是一般的众数,而是出现次数大于一半的,所以在主席树上可以直接二分,看两个子树的值域哪个大于一半,就走哪个子树,如果都为一半,返回-1。
- 树上主席树的查询不同于序列上的主席树,不是子树做差,而是子树相加减去两倍LCA对应的树,然后这样减去之后会把LCA对应的点也给减去,所以要根据LCA点权判断再加上。
- 有一道类似的题目,UVALive7831。
- 比赛时一直莫队莫队,最后还是莫不出来,太容易思想江化了。
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+50;
struct Edge{
int v,next;
}e[N*2];
int cnt,head[N],a[N];
int n,qs,u,v;
int fa[N][30],d[N],pw[30];
void init(){
cnt=0;
memset(head,-1,sizeof(head));
pw[0]=1;
for(int i=1;i<=20;i++){
pw[i]=pw[i-1]*2;
}
}
void add(int u,int v){
e[cnt]=Edge{v,head[u]};
head[u]=cnt++;
e[cnt]=Edge{u,head[v]};
head[v]=cnt++;
}
#define mid (l+r)/2
int tr[N],sum[N*30],ls[N*30],rs[N*30],tot;
void update(int pre,int &rt,int l,int r,int v){
rt=++tot;
ls[rt]=ls[pre];
rs[rt]=rs[pre];
sum[rt]=sum[pre]+1;
if(l<r){
if(v<=mid){
update(ls[pre],ls[rt],l,mid,v);
}else{
update(rs[pre],rs[rt],mid+1,r,v);
}
}
}
int query(int u,int v,int lca,int l,int r,int k,int lc){
if(l==r){
return l;
}
int ltmp=sum[ls[u]]+sum[ls[v]]-2*sum[ls[lca]]+(a[lc]>=l && a[lc]<=mid ?1:0);
int rtmp=sum[rs[u]]+sum[rs[v]]-2*sum[rs[lca]]+(a[lc]>mid && a[lc]<=r ?1:0);
if(ltmp*2>k){
return query(ls[u],ls[v],ls[lca],l,mid,k,lc);
}else if(rtmp*2>k){
return query(rs[u],rs[v],rs[lca],mid+1,r,k,lc);
}else{
return -1;
}
}
void dfs(int u){
for(int i=1;pw[i]<=d[u];i++){
fa[u][i]=fa[fa[u][i-1]][i-1];
}
update(tr[fa[u][0]],tr[u],1,n,a[u]);
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==fa[u][0]){
continue;
}
fa[v][0]=u;
d[v]=d[u]+1;
dfs(v);
}
}
int lca(int x,int y){
if(d[x]<d[y]){
swap(x,y);
}
int tmp=d[x]-d[y];
for(int i=0;pw[i]<=tmp;i++){
if(tmp&pw[i]){
x=fa[x][i];
}
}
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];
}
int main(){
// freopen("wo.txt","r",stdin);
scanf("%d%d",&n,&qs);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
init();
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
}
dfs(1);
while(qs--){
scanf("%d%d",&u,&v);
int lc=lca(u,v);
int len=d[u]+d[v]-2*d[lc]+1;
int ans=query(tr[u],tr[v],tr[lc],1,n,len,lc);
printf("%d\n",ans);
}
return 0;
}
gym102201F_Fruit Tree的更多相关文章
- [数据结构]——二叉树(Binary Tree)、二叉搜索树(Binary Search Tree)及其衍生算法
二叉树(Binary Tree)是最简单的树形数据结构,然而却十分精妙.其衍生出各种算法,以致于占据了数据结构的半壁江山.STL中大名顶顶的关联容器--集合(set).映射(map)便是使用二叉树实现 ...
- SAP CRM 树视图(TREE VIEW)
树视图可以用于表示数据的层次. 例如:SAP CRM中的组织结构数据可以表示为树视图. 在SAP CRM Web UI的术语当中,没有像表视图(table view)或者表单视图(form view) ...
- 无限分级和tree结构数据增删改【提供Demo下载】
无限分级 很多时候我们不确定等级关系的层级,这个时候就需要用到无限分级了. 说到无限分级,又要扯到递归调用了.(据说频繁递归是很耗性能的),在此我们需要先设计好表机构,用来存储无限分级的数据.当然,以 ...
- 2000条你应知的WPF小姿势 基础篇<45-50 Visual Tree&Logic Tree 附带两个小工具>
在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件工程师.最为出色的是他维护了两个博客:2,000Things You Should Know About C# 和 2,0 ...
- Leetcode 笔记 110 - Balanced Binary Tree
题目链接:Balanced Binary Tree | LeetCode OJ Given a binary tree, determine if it is height-balanced. For ...
- Leetcode 笔记 100 - Same Tree
题目链接:Same Tree | LeetCode OJ Given two binary trees, write a function to check if they are equal or ...
- Leetcode 笔记 99 - Recover Binary Search Tree
题目链接:Recover Binary Search Tree | LeetCode OJ Two elements of a binary search tree (BST) are swapped ...
- Leetcode 笔记 98 - Validate Binary Search Tree
题目链接:Validate Binary Search Tree | LeetCode OJ Given a binary tree, determine if it is a valid binar ...
- Leetcode 笔记 101 - Symmetric Tree
题目链接:Symmetric Tree | LeetCode OJ Given a binary tree, check whether it is a mirror of itself (ie, s ...
随机推荐
- 原生Js_使用setInterval() 方法实现图片轮播功能
用javascript图片轮播功能 <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...
- [CSP-S模拟测试]:迷宫(最短路)
题目传送门(内部题123) 输入格式 输入文件的第一行为四个正整数$n,m,k,d$. 接下来$m$行,每行三个整数$u,v,w$,描述一条无向道路. 输入文件最后一行包含$k$个整数,为$p_0,p ...
- 基于ElementUI,设置流体高度时,固定列与底部有间隙
基于ElementUI,设置流体高度时,固定列与底部有间隙问题,如下图: 解决办法: 1.fixed流体的高度设置为100% 2.将fixed的滚动内容的最大高度设置为none,bottom为 ...
- C1:DOM 元素的尺寸和位置
DOM元素的尺寸和位置 DOM 元素的尺寸 DOM.offsetWidth/offsetHeight: 包括内容区宽/高,padding,border,不包括margin.如果元素的box-sizei ...
- vue中bus.$on事件被多次绑定
问题描述:只要页面没有强制刷新,存在组件切换,bus.$on方法会被多次绑定,造成事件多次触发 解决办法一:在每次调用方法前先解绑事件( bus.$off ),然后在重新绑定( bus.$on ) b ...
- LeetCode82----删除排序链表中的重复元素 II
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 示例 1: 输入: 1->2->3->3->4->4->5 输出: 1-&g ...
- swift模式和模式匹配
模式和模式匹配 模式: 代表单个或者复合值得结构,也就是说模式不是一个特定的值,它是一种抽象的结构,[一句话,不是特指,是泛指].这样就可以用模式来匹配各种各样的值. 例如:(x,y)可以匹配元祖(1 ...
- TCP定时器 之 重传定时器
注:这部分还没有完全分析透彻,先在此记录,后面回顾的时候再进行补充: 启动定时器: (1) 之前发送的数据段已经得到确认,新发出一个数据段之后设定: (2) 新建连接发送syn之后设定: (3) PM ...
- 一、基础篇--1.1Java基础-Object类中常见的方法,为什么wait notify会放在Object里边
这是个设计相关的问题,它考察的是面试者对现有系统和一些普遍存在但看起来不合理的事物的看法.回答这些问题的时候,你要说明为什么把这些方法放在Object类里是有意义的,还有不把它放在Thread类里的原 ...
- Java: Integer用==比较时127相等128不相等的原因
直接看问题吧 for (int i = 0; i < 150; i++) { Integer a = i; Integer b = i; System.out.println(i + " ...