首页 > 其他分享 >【解题报告】SP10628 COT-Count on a tree

【解题报告】SP10628 COT-Count on a tree

时间:2022-09-22 20:22:29浏览次数:88  
标签:Count ch COT int top tree son LCA include

SP10628 COT

这道题的传送门

双倍经验,两个题一样的啦

简要题意

给出一颗n个节点的树,每个节点都有一个权值,求u到v的第k小权值

其实就是树上的区间第k小

主席树+树上差分

先想一想序列上的怎么做

当然就是主席树啦(不会的点这里

然后想一想树上怎么搞

可以进行树上差分

一般分为两种:点/边上的差分

点上的:u到根+v到根-LCA到根-LCA的爹到根(指路径上点的权值)

边上的:u到根+v到根-2*(LCA到根)(指路径上边的权值)

这里的LCA我用树剖来求QWQ

而在这道题里明显是针对点的树上差分

和普通的主席树差不多啦,就是多了几个参数(LCA和它爹)

AC 代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>

using namespace std;

const int maxn=100010;

inline int read()
{
	int w=0,f=1;
	char ch=getchar();
	while(ch<'0' || ch>'9')
	{
		if(ch=='-')
		{
			f=-1;
		}
		ch=getchar();
	}
	while(ch>='0' && ch<='9')
	{
		w=(w<<3)+(w<<1)+(ch^48);
		ch=getchar();
	}
	return w*f;
}

int cnt,num;

int n,m,tot;

int fa[maxn];

int id[maxn];

int val[maxn];

int fub[maxn];

int siz[maxn];

int head[maxn];

int deep[maxn];

int top[maxn];

int root[maxn];

int max_son[maxn];

struct s_t
{
	int ls;
	int rs;
	int sum;
}t[maxn<<5];

struct edge
{
	int to;
	int val;
	int next;
}e[maxn*2];

void add(int x,int y)
{
	tot++;
	e[tot].to=y;
	e[tot].next=head[x];
	head[x]=tot;
}

void update(int &p,int las,int l,int r,int k) //主席树板子
{
	p=++cnt;
	
	t[p]=t[las];
	
	if(l==r)
	{
		t[p].sum++;
		return ;
	}
	
	int mid=(l+r)>>1;
	
	if(k<=mid)
	{
		update(t[p].ls,t[las].ls,l,mid,k);
	}
	else
	{
		update(t[p].rs,t[las].rs,mid+1,r,k);
	}
	t[p].sum=t[t[p].ls].sum+t[t[p].rs].sum;
}

int query(int p,int las,int lca,int fa_lca,int l,int r,int k)
{
	if(l==r)
	{
		return l;
	}
	
	int mid=(l+r)>>1;
	
	int sum=t[t[p].ls].sum+t[t[las].ls].sum-t[t[lca].ls].sum-t[t[fa_lca].ls].sum;
	
	if(k<=sum)
	{
		return query(t[p].ls,t[las].ls,t[lca].ls,t[fa_lca].ls,l,mid,k);
	}
	else
	{
		return query(t[p].rs,t[las].rs,t[lca].rs,t[fa_lca].rs,mid+1,r,k-sum);
	}
}

void dfs_first(int x,int fath) //树剖求LCA
{
	update(root[x],root[fath],1,num,val[x]);
	fa[x]=fath;
	deep[x]=deep[fath]+1;
	siz[x]=1;
	for(int i=head[x];i;i=e[i].next)
	{
		int to=e[i].to;
		if(to==fath)
		{
			continue;
		}
		dfs_first(to,x);
		siz[x]+=siz[to];
		if(siz[to]>siz[max_son[x]])
		{
			max_son[x]=to;
		}
	}
}

void dfs_second(int x,int t)
{
	tot++;
	id[x]=tot;
	top[x]=t;
	e[tot].val=val[x];
	if(max_son[x]==0)
	{
		return ;
	}
	dfs_second(max_son[x],top[x]);
	for(int i=head[x];i;i=e[i].next)
	{
		int to=e[i].to;
		if(to!=fa[x] && to!=max_son[x])
		{
			dfs_second(to,to);
		}
	}
}

int LCA(int x,int y)
{
	while(top[x]!=top[y])
	{
		if(deep[top[x]]<deep[top[y]])
		{
			swap(x,y);
		}
		x=fa[top[x]];
	}
	return deep[x]<deep[y] ? x : y;
}

int main()
{
	freopen("qwq.in","r",stdin);
	freopen("qwq.out","w",stdout);
	
	n=read();
	m=read();
	
	for(int i=1;i<=n;i++)
	{
		fub[i]=val[i]=read();
	}
	
	sort(fub+1,fub+n+1); //离散化
	
	num=unique(fub+1,fub+n+1)-fub-1;
	
	for(int i=1;i<=n;i++)
	{
		val[i]=lower_bound(fub+1,fub+num+1,val[i])-fub;
	}
	
	for(int i=1;i<n;i++)
	{
		int u=read();
		int v=read();
		add(u,v);
		add(v,u);
	}
	
	tot=0;
	
	dfs_first(1,0);
	
	tot=0;
	
	dfs_second(1,1);
	
	for(int i=1;i<=m;i++)
	{
		int u=read();
		int v=read();
		int k=read();
		int lca=LCA(u,v);
		cout<<fub[query(root[u],root[v],root[lca],root[fa[lca]],1,num,k)]<<endl;
	}
	
	fclose(stdin);
	fclose(stdout);
	
	return 0;
}

真是道大水题呢QWQ

标签:Count,ch,COT,int,top,tree,son,LCA,include
From: https://www.cnblogs.com/SitoASK/p/16720746.html

相关文章

  • CF1540B Tree Array 题解
    CF1540BTreeArray给定一棵\(n\)个节点的树。对于这棵树,我们通过下列方法来生成一个序列:等概率选择这\(n\)个节点中的一个节点,并对这个节点打上标记(初始时没有节......
  • CodeTON Round 2 (Div. 1 + Div. 2) - E. Count Seconds
    思维+DP[Problem-E-Codeforces](https://codeforces.com/contest/1695/problem/D2)题意给一张有\(n\)个结点\(m\)条有向边的有向无环图,\(1<=n,m<=1000\),每......
  • [AAAI 2022]Graph Convolutional Networks with Dual Message Passing for Subgraph I
    总结GNN实现子图匹配。利用线图(边变点)让模型训练时将点和边的特征反复映射到对方领域参与训练。定义常规符号Graph,Edge,Vertex,。X,Y表示点标签和边标签:\(\mathca......
  • WebForm中的treeView的简单使用
    我们要使用treeView,首先需要对应树状图关系的表结构,如省市区的结构,大概如下 完成效果图(省市区结构),大概如下: 新增一个citys.aspx页面,在页面中添加treeView<div>......
  • leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal 从前序与
    一、题目大意给定两个整数数组preorder和inorder,其中preorder是二叉树的先序遍历,inorder是同一棵树的中序遍历,请构造二叉树并返回其根节点。示例1:输入:pre......
  • Antd Tree,实现排序拖动,父子层级内外拖动
    拖动属性dropToGap,dropPosition属性解释:dropToGap:boolean类型,true代表拖拽到节点之间的缝隙中,false代表拖拽到节点上,即节点的内容区。dropPosition:拖拽的时候,针对一......
  • Java并发编程解析 | 基于JDK源码解析Java领域中并发锁之同步器Semaphore,CyclicBarrier
    苍穹之边,浩瀚之挚,眰恦之美;悟心悟性,善始善终,惟善惟道!——朝槿《朝槿兮年说》写在开头在并发编程领域,有两大核心问题:一个是互斥,即同一时刻只允许一个线程访问共享......
  • 使用element-tree实现id相同的选择
    最近做一个项目,需要树形结构中 id相同的数据,选中或取消一个,其他的也要选中和取消。上网查案例,有一个需求相同的,但是需要修改源码。我觉得不靠谱。于是乎,自己写了一个,供......
  • IfcDimensionCount
    IfcDimensionCount类型定义IfcDimensionCount定义坐标空间的维度。在本规范中,尺寸限制为1、2或3。 注:分配给几何表示上下文的形状表示可能包括低维度的几何表示项目,特......
  • 大家都在用MySQL count(*)统计总数,到底有什么问题?
    在日常开发工作中,我经常会遇到需要统计总数的场景,比如:统计订单总数、统计用户总数等。一般我们会使用MySQL的count函数进行统计,但是随着数据量逐渐增大,统计耗时也越来越长......