bzoj2588(主席树+dfs序)

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


强制在线水不过去了呀
树上路径,我们考虑按照dfs序建主席树。
那我们通过差分的思想就可以搞出路径上数值建立的权值线段树。

#include<bits/stdc++.h>
using namespace std;
int n,m,hash[101000],t,t1,tp,hash_new[101000],bj[101000],f[101000],deep[101000],lastans; //hash表示数字与等级的映射,hash_new代表新数组 
int fa[101000][21],f_a,f_b,f_x,f_y;
struct node{int n,y;}e[201000];
int linkk[101000],te,dfs_in[101000],dfs_out[101000],tt;
bool vis[101000];
struct tree{int ls,rs,num;}tree[101000*50];
struct old{int num,id;}a[101000];
struct point{int num,time;}a_p[101000];
struct dfsa{int num,place;}dfs_end[101000];
int read() 
{ 
    bool flag=true; 
    int num=0;char c=getchar(); 
    for(;c<'0'||c>'9';c=getchar())if(c=='-') flag=false; 
    for(;c>='0'&&c<='9';c=getchar()) 
    num=(num<<3)+(num<<1)+c-48; 
    if(flag) return num; 
     else return -num; 
}
bool mycup(old a,old b){return a.num<b.num;}
bool mycup1(dfsa a,dfsa b){return a.place<b.place;}
bool mycup2(point a,point b){return a.time<b.time;}
void dfs(int x,int father)
{
    a_p[x].time=++tp;
    deep[x]=deep[father]+1;  
    dfs_in[x]=++tt;
    fa[x][0]=father;
    for(int i=linkk[x];i;i=e[i].n) 
      if(e[i].y!=father) dfs(e[i].y,x);
    dfs_out[x]=tt;
}
void init()
{
    memset(fa,-1,sizeof(fa));
    n=read();m=read();
    for(int i=1;i<=n;++i)
     {
      a[i].num=read();
      a[i].id=i;
      a_p[i].num=i; 
     } 
    sort(a+1,a+n+1,mycup);
    for(int i=1;i<=n;++i)
     if(a[i].num!=a[i-1].num)
      hash[++t]=a[i].num,hash_new[a[i].id]=t;
     else
      hash_new[a[i].id]=t;
    for(int i=1;i<=n-1;++i) 
     {
      int aa=read(),bb=read();
      e[++te].y=bb;
      e[te].n=linkk[aa]; 
      linkk[aa]=te; 
      e[++te].y=aa;
      e[te].n=linkk[bb];
      linkk[bb]=te;
     }
    dfs(1,0);
    for(int i=1;i<=n;++i) dfs_end[i].num=i,dfs_end[i].place=dfs_out[i]+1; 
    sort(dfs_end+1,dfs_end+n+1,mycup1);
    return;
}
void delite(int &root,int last,int l,int r,int num)
{
    if(!(l==1&&r==n)) 
     {
      root=++t1;
      tree[root].ls=tree[last].ls;
      tree[root].rs=tree[last].rs;
     }
    tree[root].num=tree[last].num-1;
    int mid=(l+r)>>1;
    if(l==r) return;
    if(num<=mid) delite(tree[root].ls,tree[last].ls,l,mid,num);
    else delite(tree[root].rs,tree[last].rs,mid+1,r,num);
}
void build(int &root,int last,int l,int r,int num)
{
    root=++t1;
    tree[root].num=tree[last].num+1;
    int mid=(l+r)>>1;
    tree[root].ls=tree[last].ls;
    tree[root].rs=tree[last].rs;
    if(l==r)  return;
    if(num<=mid) build(tree[root].ls,tree[last].ls,l,mid,num);
    else build(tree[root].rs,tree[last].rs,mid+1,r,num);
    return;
}
void change(bool flag)
{
    if(flag)
     {
      f_a=tree[f_a].ls;
      f_b=tree[f_b].ls;
      f_x=tree[f_x].ls;
      f_y=tree[f_y].ls;
     }
    else
     {
      f_a=tree[f_a].rs;
      f_b=tree[f_b].rs;
      f_x=tree[f_x].rs;
      f_y=tree[f_y].rs;
     }
    return;
}
int find(int l,int r,int k)
{
    if(l==r) return l;
    int mid=(l+r)>>1;
    int sum=tree[tree[f_x].ls].num+tree[tree[f_y].ls].num-tree[tree[f_a].ls].num-tree[tree[f_b].ls].num;
    if(k<=sum) return change(1),find(l,mid,k);
    else return change(0),find(mid+1,r,k-sum);
}
int lca(int a,int b)
{
    if(deep[a]<deep[b]) swap(a,b);
    int i;
    for(i=0;(1<<i)<=deep[a];i++); i--;
    for(int j=i;j>=0;j--) 
     if(deep[a]-(1<<j)>=deep[b]) a=fa[a][j]; 
    if(a==b) return a;
    for(int j=i;j>=0;j--)
     if(fa[a][j]!=0&&fa[a][j]!=fa[b][j])
      a=fa[a][j],b=fa[b][j];
    return fa[a][0];
}
void work()
{ 
    memset(tree,0,sizeof(tree));
    int j=1;
    sort(a_p+1,a_p+n+1,mycup2);
    for(int i=1;i<=n;++i) 
     {
      build(f[i],f[i-1],1,n,hash_new[a_p[i].num]);
      bj[a_p[i].num]=i;
      while(dfs_end[j].place==i) delite(f[i],f[i],1,n,hash_new[dfs_end[j].num]),j++; 
     } 
    for(int i=1;i<=20;++i)
      for(int j=1;j<=n;++j)
        fa[j][i]=fa[fa[j][i-1]][i-1];
    for(int i=1;i<=m;++i)
     {
      f_x=read(),f_y=read();
      f_x^=lastans;
      int w=lca(f_x,f_y);
      f_x=f[bj[f_x]];f_y=f[bj[f_y]];  
      f_a=f[bj[w]];f_b=f[bj[fa[w][0]]];
      int zz=read();     
      lastans=hash[find(1,n,zz)]; 
      printf("%d\n",lastans);
     }
    return;
}
int main()
{
    init();
    work();
    return 0; 
}

猜你喜欢

转载自blog.csdn.net/a1035719430/article/details/81143080