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