BZOJ 2588 Count on a tree (COT) 是持久的段树

BZOJ 2588 Count on a tree (COT) 是持久的段树

大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。

标题效果:两棵树之间的首次查询k大点的权利。

思维:树木覆盖树,事实上,它是正常的树木覆盖了持久段树。

由于使用权值段树可以寻求区间k大,然后应用到持久段树思想,间隔可以做减法。详见代码。

CODE:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 100010
#define NIL (tree[0])
using namespace std;

pair<int,int> src[MAX];

struct Complex{
	Complex *son[2];
	int cnt;

	Complex(Complex *_,Complex *__,int ___):cnt(___) {
		son[0] = _;
		son[1] = __;
	}
	Complex() {}
}*tree[MAX];

int points,asks;
int xx[MAX];

int head[MAX],total;
int next[MAX << 1],aim[MAX << 1];

int father[MAX][20],deep[MAX];

inline void Add(int x,int y);
void DFS(int x);
void SparseTable();

Complex *BuildTree(Complex *pos,int x,int y,int val);
int GetAns(Complex *l,Complex *r,Complex *f,Complex *p,int x,int y,int k);
int GetLCA(int x,int y);
int Ask(int x,int y,int k);

int main()
{
	cin >> points >> asks;
	for(int i = 1;i <= points; ++i)
		scanf("%d",&src[i].first),src[i].second = i;
	sort(src + 1,src + points + 1);
	for(int i = 1;i <= points; ++i)
		xx[src[i].second] = i;
	for(int x,y,i = 1;i < points; ++i) {
		scanf("%d%d",&x,&y);
		Add(x,y),Add(y,x);
	}
	NIL = new Complex(NULL,NULL,0);
	NIL->son[0] = NIL->son[1] = NIL;
	DFS(1);
	SparseTable();
	int now = 0;
	for(int x,y,k,i = 1;i <= asks; ++i) {
		scanf("%d%d%d",&x,&y,&k);
		printf("%d",now = src[Ask(x ^ now,y,k)].first);
		if(i != asks)	puts("");
	}
	return 0;
}

inline void Add(int x,int y)
{
	next[++total] = head[x];
	aim[total] = y;
	head[x] = total;
}

void DFS(int x)
{
	deep[x] = deep[father[x][0]] + 1;
	tree[x] = BuildTree(tree[father[x][0]],1,points,xx[x]);
	for(int i = head[x];i;i = next[i]) {
		if(aim[i] == father[x][0])	continue;
		father[aim[i]][0] = x;
		DFS(aim[i]);
	}
}

void SparseTable()
{
	for(int j = 1;j <= 19; ++j)
		for(int i = 1;i <= points; ++i)
			father[i][j] = father[father[i][j - 1]][j - 1];
}

int Ask(int x,int y,int k)
{
	int lca = GetLCA(x,y);
	return GetAns(tree[x],tree[y],tree[lca],tree[father[lca][0]],1,points,k);
}

Complex *BuildTree(Complex *pos,int x,int y,int val)
{
	int mid = (x + y) >> 1;
	if(x == y)	return new Complex(NIL,NIL,pos->cnt + 1);
	if(val <= mid)	return new Complex(BuildTree(pos->son[0],x,mid,val),pos->son[1],pos->cnt + 1);
	return new Complex(pos->son[0],BuildTree(pos->son[1],mid + 1,y,val),pos->cnt + 1);	
}

int GetLCA(int x,int y)
{
	if(deep[x] < deep[y])	swap(x,y);
	for(int i = 19; ~i; --i)
		if(deep[father[x][i]] >= deep[y])
			x = father[x][i];
	if(x == y)	return x;
	for(int i = 19; ~i; --i)
		if(father[x][i] != father[y][i])
			x = father[x][i],y = father[y][i];
	return father[x][0];
}

int GetAns(Complex *l,Complex *r,Complex *f,Complex *p,int x,int y,int k)
{
	if(x == y)	return x;
	int mid = (x + y) >> 1;
	int temp = l->son[0]->cnt + r->son[0]->cnt - f->son[0]->cnt - p->son[0]->cnt;
	if(k <= temp)	return GetAns(l->son[0],r->son[0],f->son[0],p->son[0],x,mid,k);
	return GetAns(l->son[1],r->son[1],f->son[1],p->son[1],mid + 1,y,k - temp);
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/117451.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • scala , spark-shell 命令行无法撤销,删除 ,退格 ,回退

    scala , spark-shell 命令行无法撤销,删除 ,退格 ,回退scala , spark-shell 命令行无法撤销,删除 ,退格 ,回退

    2022年4月23日
    146
  • Java学习笔记–StringTokenizer的使用「建议收藏」

    Java学习笔记–StringTokenizer的使用「建议收藏」拓展:Pattern.split替代String.splithttp://www.cnblogs.com/gnivor/p/4386978.htmlStringTokenizer是一个用来分隔St

    2022年7月2日
    29
  • linux查看端口号占用命令-netstat

    linux查看端口号占用命令-netstat题记经常会发现,很多时候我们在运行一些带有端口的程序时,程序经常会报端口被占用的问题,比如Tomcat8080,端口起不来。查看端口号netstat如果发现某个端口被占用后,可以用命令查看,该端口到底是被哪个进程所占用。命令如下:netstat-pan|grep5623#其中5623位端口号如图:发现5623的端口,被28425的进程id所占用,继

    2022年7月23日
    13
  • 说一下CAS锁机制?「建议收藏」

    1.CAS(CompareandSwap比较并交换),是一种无锁算法,当多个线程尝试使用CAS同时更新同一个变量时,只有其中一个线程能更新变量的值,而其他线程都失败,失败的线程并不会挂起,而是被告知这次竞争中失败,并可以再次尝试。2.CAS算法涉及到三个操作数a.需要读写的内存位置(V)b.进行比较的预期原值(A)c.拟写入的新值(B)3.如果内存位置V的值与预期原值A相匹配,那么处理器会自动将该位置值更新为新值B,否则处理器不做任何操作。java多线程总结篇4——锁机制…

    2022年4月17日
    50
  • 关于JavaScript闭包理解

    关于JavaScript闭包理解js 的作用域分两种 和 基于所熟悉的作用域链相关知识 知道在 js 作用域环境中访问变量的权利是的 内部作用域可以获得当前作用域下的变量并且可以获得当前包含当前作用域的外层作用域下的变量 反之则不能 也就是说在外层作用域下无法获取内层作用域下的变量 同样在不同的函数作用域中也是不能相互访问彼此变量的 那么想在一个函数内部也有限权访问另一个函数内部的变量该怎么办呢 闭包就是用来解决这一需求的 我们首先知道闭包有 3 个特性 函数嵌套函数 函数内部可以引用函数外部的参数和变量 参数和变量不会被垃圾回收机制回

    2025年9月16日
    2
  • 414 request url too large

    414 request url too large粘贴图片时,拿到的base64图片地址太长,报错,有2种方法解决1、ajax传输为get方法,get方法有限制,改为post;2、把server的server.xml添加上

    2022年5月9日
    52

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号