Bzoj 2588: Spoj 10628. Count on a tree 主席树,离散化,可持久,倍增LCA

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2588

2588: Spoj 10628. Count on a tree

Time Limit: 12 Sec  Memory Limit: 128 MB
Submit: 3584  Solved: 835
[Submit][Status][Discuss]

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

暴力自重。。。

Source

鸣谢seter

题解:

在树上建主席树,记得最后一行后没有空格,否则PE.

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define MAXN 100010
  4 struct node
  5 {
  6     int begin,end,next;
  7 }edge[MAXN*2];
  8 struct NODE
  9 {
 10     int left,right;
 11 }tree[MAXN*20];
 12 int cnt,Head[MAXN],n,SIZE,value[MAXN],pos[MAXN],deep[MAXN],P[MAXN][17],sum[MAXN*20],a[MAXN],val[MAXN],root[MAXN],tot;
 13 bool vis[MAXN];
 14 void addedge(int bb,int ee)
 15 {
 16     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
 17 }
 18 void addedge1(int bb,int ee)
 19 {
 20     addedge(bb,ee);addedge(ee,bb);
 21 }
 22 int read()
 23 {
 24     int s=0,fh=1;char ch=getchar();
 25     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
 26     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
 27     return s*fh;
 28 }
 29 void dfs1(int u)
 30 {
 31     int i,v;
 32     SIZE++;value[SIZE]=u;pos[u]=SIZE;
 33     vis[u]=true;
 34     for(i=Head[u];i!=-1;i=edge[i].next)
 35     {
 36         v=edge[i].end;
 37         if(vis[v]==false)
 38         {
 39             deep[v]=deep[u]+1;
 40             P[v][0]=u;
 41             dfs1(v);
 42         }
 43     }
 44 }
 45 void Ycl()
 46 {
 47     int i,j;
 48     for(j=1;(1<<j)<=n;j++)
 49     {
 50         for(i=1;i<=n;i++)
 51         {
 52             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
 53         }
 54     }
 55 }
 56 int LCA(int x,int y)
 57 {
 58     int i,j;
 59     if(deep[x]<deep[y])swap(x,y);
 60     for(i=0;(1<<i)<=deep[x];i++);i--;
 61     for(j=i;j>=0;j--)if(deep[x]-(1<<j)>=deep[y])x=P[x][j];
 62     if(x==y)return x;
 63     for(j=i;j>=0;j--)
 64     {
 65         if(P[x][j]!=-1&&P[x][j]!=P[y][j])
 66         {
 67             x=P[x][j];
 68             y=P[y][j];
 69         }
 70     }
 71     return P[x][0];
 72 }
 73 void Update(int x,int &y,int l,int r,int k)
 74 {
 75     y=++SIZE;
 76     sum[y]=sum[x]+1;
 77     if(l==r)return;
 78     tree[y].left=tree[x].left;tree[y].right=tree[x].right;
 79     int mid=(l+r)/2;
 80     if(k<=mid)Update(tree[x].left,tree[y].left,l,mid,k);
 81     else Update(tree[x].right,tree[y].right,mid+1,r,k);
 82 }
 83 int query(int l,int r,int A,int B,int C,int D,int k)
 84 {
 85     if(l==r)return l;
 86     int mid=(l+r)/2,tmp=sum[tree[A].left]+sum[tree[B].left]-sum[tree[C].left]-sum[tree[D].left];
 87     if(k<=tmp)return query(l,mid,tree[A].left,tree[B].left,tree[C].left,tree[D].left,k);
 88     else return query(mid+1,r,tree[A].right,tree[B].right,tree[C].right,tree[D].right,k-tmp);
 89 }
 90 int Query(int A,int B,int k)
 91 {
 92     int C=LCA(A,B),D=P[C][0];
 93     A=root[pos[A]];B=root[pos[B]];C=root[pos[C]];D=root[pos[D]];
 94     return query(1,tot,A,B,C,D,k);
 95 }
 96 int main()
 97 {
 98     int m,i,bb,ee,k,k1,lastans,U,V,K;
 99     n=read();m=read();
100     for(i=1;i<=n;i++)a[i]=val[i]=read();
101     sort(val+1,val+n+1);
102     tot=unique(val+1,val+n+1)-(val+1);
103     memset(Head,-1,sizeof(Head));cnt=1;
104     for(i=1;i<n;i++)
105     {
106         bb=read();ee=read();
107         addedge1(bb,ee);
108     }
109     memset(P,-1,sizeof(P));SIZE=0;
110     memset(value,0,sizeof(value));//树上每个编号的实际的点.
111     memset(pos,0,sizeof(pos));//每个点在树上的编号.
112     dfs1(1);Ycl();
113     memset(root,0,sizeof(root));
114     SIZE=0;
115     for(i=1;i<=n;i++)//i为树上的节点.(即i为每个点在树上的编号.)
116     {
117         k=value[i];
118         k1=lower_bound(val+1,val+tot+1,a[k])-val;
119         Update(root[pos[P[k][0]]],root[i],1,tot,k1);
120     }
121     lastans=0;
122     for(i=1;i<=m;i++)
123     {
124         U=read();V=read();K=read();
125         U^=lastans;
126         lastans=val[Query(U,V,K)];
127         printf("%d",lastans);
128         if(i!=m)printf("
");
129     }
130     fclose(stdin);
131     fclose(stdout);
132     return 0;
133 }
View Code
原文地址:https://www.cnblogs.com/Var123/p/5276903.html