bzoj2588:Count on a tree(可持久化线段树+Lca)

2588: Spoj 10628. Count on a tree

Time Limit: 12Sec  Memory Limit: 128 MB
Submit: 5524  Solved: 1306

Description

给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。

Input

第一行两个整数N,M。

第二行有N个整数,其中第i个整数表示点i的权值。

后面N-1行每行两个整数(x,y),表示点x到点y有一条边。

最后M行每行两个整数(u,v,k),表示一组询问。

Output

M行,表示每个询问的答案。最后一个询问不输出换行符

Sample Input

8 5

105 2 9 3 8 5 7 7

1 2

1 3

1 4

3 5

3 6

3 7

4 8

2 5 1

0 5 2

10 5 3

11 5 4

110 8 2

Sample Output

2

8

9

105

7

HINT

HINT:

N,M<=100000

题目分析:可持久化线段树,一个节点以它的fa的线段树作为历史版本做适当修改。当我们要查u->v的路径第k小时,我们同时在u,v,lca(u,v),fa[lca(u,v)]四棵树上进行二叉查找。

写代码的时候发现与其将空子树指向NULL还不如指向池子的第0位,然后让第0位指向自身。这样Query的时候就可以在0的地方不停地打转,不会爆栈。

没看清输出格式,PE了一发……

CODE:

#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

const int maxn=100100;
const int maxl=20;
const int oo=1000000001;

struct data
{
	int obj;
	data *Next;
} e[maxn<<1];
data *head[maxn];
int cur=-1;

struct Tnode
{
	int num;
	Tnode *lson,*rson;
} tree[(maxn<<2)+maxn*maxl];
Tnode *Root[maxn];
int Tcur=-1;

struct Input
{
	int Time,val,place;
} a[maxn];
int id[maxn];
int temp=0;

int fa[maxn][maxl];
int dep[maxn];

int n,m;

void Add(int x,int y)
{
	cur++;
	e[cur].obj=y;
	e[cur].Next=head[x];
	head[x]=e+cur;
}

bool Comp1(Input x,Input y)
{
	return x.valnum++;
		return;
	}
	
	int mid=(L+R)>>1;
	if (x<=mid)
	{
		Tnode *y=root->lson;
		root->lson=New_node();
		*(root->lson)=*y;
		Update(root->lson,L,mid,x);
	}
	else
	{
		Tnode *y=root->rson;
		root->rson=New_node();
		*(root->rson)=*y;
		Update(root->rson,mid+1,R,x);
	}
	
	root->num=root->lson->num+root->rson->num;
}

void Dfs(int node)
{
	Root[node]=New_node();
	*Root[node]=*Root[ fa[node][0] ];
	Update(Root[node],1,temp,a[node].place);
	data *p;
	for (p=head[node]; p; p=p->Next)
		if (p->obj!=fa[node][0])
		{
			int son=p->obj;
			fa[son][0]=node;
			dep[son]=dep[node]+1;
			Dfs(son);
		}
}

void Make_fa()
{
	for (int j=1; j=0; j--)
		if ( dep[ fa[u][j] ]>=dep[v] )
			u=fa[u][j];
	if (u==v) return u;
	for (int j=maxl-1; j>=0; j--)
		if (fa[u][j]!=fa[v][j])
		{
			u=fa[u][j];
			v=fa[v][j];
		}
	return fa[u][0];
}

int Query(Tnode *ru,Tnode *rv,Tnode *rw,Tnode *rfw,int L,int R,int k)
{
	if (L==R) return L;
	int left_num=ru->lson->num+rv->lson->num-rw->lson->num-rfw->lson->num;
	int mid=(L+R)>>1;
	if (k<=left_num) return Query(ru->lson,rv->lson,rw->lson,rfw->lson,L,mid,k);
	else return Query(ru->rson,rv->rson,rw->rson,rfw->rson,mid+1,R,k-left_num);
}

int main()
{
	freopen("c.in","r",stdin);
	freopen("c.out","w",stdout);
	
	scanf("%d%d",&n,&m);
	for (int i=1; i<=n; i++) scanf("%d",&a[i].val);
	for (int i=1; i<=n; i++) a[i].Time=i;
	for (int i=1; i<=n; i++) head[i]=NULL;
	for (int i=1; i

你可能感兴趣的:(Lca,可持久化数据结构)