【刷题】BZOJ 2588 Spoj 10628. Count on a tree

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

N,M<=100000

Solution

一个典型的树上差分,然后维护第\(k\)大。。主席树嘛
我们主席树的每个版本是从它的父亲处继承过来的,那么它维护的就是这个节点到根节点路径上的信息
那么我们的差分就是

\[ans=find(T_{u}+T_{v}-T_{lca}-T_{lca'fa}) \]

查询就在这个差分后的树上找就行了

#include<bits/stdc++.h>
#define ll long long
#define db double
#define ld long double
#define Mid ((l+r)>>1)
#define lson l,Mid
#define rson Mid+1,r
const int MAXN=100000+10;
int n,m,A[MAXN],Jie[MAXN][20],dep[MAXN],e,beg[MAXN],nex[MAXN<<1],to[MAXN<<1],ans;
std::vector<int> V;
std::map<int,int> M;
struct ChairMan_Tree{
    int cnt,lc[MAXN<<5],rc[MAXN<<5],sum[MAXN<<5],root[MAXN];
	inline void init()
	{
		cnt=0;
		memset(lc,0,sizeof(lc));
		memset(rc,0,sizeof(rc));
		memset(sum,0,sizeof(sum));
	}
    inline void Build(int &rt,int l,int r)
    {
        rt=++cnt;
        sum[rt]=0;
        if(l==r)return ;
        Build(lc[rt],lson);
        Build(rc[rt],rson);
    }
    inline void Insert(int &rt,int l,int r,int last,int pos)
    {
        rt=++cnt;
        sum[rt]=sum[last]+1;
        lc[rt]=lc[last];
        rc[rt]=rc[last];
        if(l==r)return ;
        else
        {
			if(pos<=Mid)Insert(lc[rt],lson,lc[last],pos);
			else Insert(rc[rt],rson,rc[last],pos);
        }
    }
	inline int Query(int left,int right,int gfa,int grand,int l,int r,int k)
	{
		if(l==r)return l;
		else
		{
			int t=sum[lc[left]]+sum[lc[right]]-sum[lc[gfa]]-sum[lc[grand]];
			if(k<=t)return Query(lc[left],lc[right],lc[gfa],lc[grand],lson,k);
			else return Query(rc[left],rc[right],rc[gfa],rc[grand],rson,k-t);
		}
	}
};
ChairMan_Tree T;
template<typename T> inline void read(T &x)
{
    T data=0,w=1;
    char ch=0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar(x%10+'0');
    if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y)
{
    to[++e]=y;
    nex[e]=beg[x];
    beg[x]=e;
}
inline void discre()
{
    sort(V.begin(),V.end());
    V.erase(unique(V.begin(),V.end()),V.end());
    for(register int i=1;i<=n;++i)
    {
        int pre=A[i];
        A[i]=lower_bound(V.begin(),V.end(),A[i])-V.begin()+1;
        M[A[i]]=pre;
    }
}
inline void dfs(int x,int f,int d)
{
	T.Insert(T.root[x],1,n,T.root[f],A[x]);
	dep[x]=d;
	Jie[x][0]=f;
	for(register int i=beg[x];i;i=nex[i])
		if(to[i]==f)continue;
		else dfs(to[i],x,d+1);
}
inline void init()
{
	for(register int j=1;j<20;++j)
		for(register int i=1;i<=n;++i)Jie[i][j]=Jie[Jie[i][j-1]][j-1];
}
inline int LCA(int u,int v)
{
	if(dep[u]<dep[v])std::swap(u,v);
	if(dep[u]>dep[v])
		for(register int i=19;i>=0;--i)
			if(dep[Jie[u][i]]>=dep[v])u=Jie[u][i];
	if(u==v)return u;
	for(register int i=19;i>=0;--i)
		if(Jie[u][i]!=Jie[v][i])u=Jie[u][i],v=Jie[v][i];
	return Jie[u][0];
}
int main()
{
    read(n);read(m);
    for(register int i=1;i<=n;++i)
    {
        read(A[i]);
        V.push_back(A[i]);
    }
    discre();
    for(register int i=1;i<n;++i)
    {
        int u,v;
        read(u);read(v);
        insert(u,v);
        insert(v,u);
    }
	T.init();
	T.Build(T.root[0],1,n);
	dfs(1,0,1);
	init();
    while(m--)
    {
        int u,v,k,lca;
        read(u);read(v);read(k);
        u^=ans;
		lca=LCA(u,v);
        ans=M[T.Query(T.root[u],T.root[v],T.root[Jie[lca][0]],T.root[lca],1,n,k)];
		write(ans,'\n');
    }
    return 0;
}

posted @ 2018-03-21 20:44  HYJ_cnyali  阅读(175)  评论(0编辑  收藏  举报