luogu2633 Count on a tree(树上LCA+主席树求区间第k小)
传送:
https://www.luogu.org/problem/P2633
题意:
给定一棵$N$个节点的树,每个点有一个权值,对于$M$个询问$(u,v,k)$,你需要回答$u xor lastans$和$v$这两个节点间第$K$小的点权。其中$lastans$是上一个询问的答案,初始为0,即第一个询问的u是明文。
数据范围:
$1<=n,m<=1e5$。
分析:
一维状态下的求区间第k小,用主席树维护,$n$棵树代表$n$个下标(位置),那么对于树上的结构怎么表示先后关系呢?
很容易想到父亲与儿子,那么可以建立$n$棵树,儿子的树是在父亲的树的基础上建立的。因为从根节点出发,一定会经过父亲到达某个点。
对于$u$到$v$的路径上的答案,可以表示为:
$num[u]-num[lca(u,v)]+num[v]-num[lca(u,v)]+num[lca(u,v)]-num[lca(lca(u,v))]$
$=num[u]+num[v]-num[lca(u,v)]-num[lca(lca(u,v))]$。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 struct node{ 5 int to,nxt; 6 }edge[maxn*2]; 7 struct node2{ 8 int l,r,num; 9 }tree[maxn*70]; 10 int num=0,size=0,N,tot,a[maxn],refl[maxn],head[maxn],fa[maxn][30],deep[maxn],root[maxn]; 11 void add(int x,int y){ 12 edge[++num]={y,head[x]};head[x]=num; 13 } 14 void update(int &x,int y,int l,int r,int dex){ 15 x=++size;tree[x]=tree[y];tree[x].num++; 16 if (l==r) return ; 17 int mid=(l+r)>>1; 18 if (dex<=mid) update(tree[x].l,tree[y].l,l,mid,dex); 19 else update(tree[x].r,tree[y].r,mid+1,r,dex); 20 } 21 int LCA(int x,int y){ 22 if (deep[x]>deep[y]) swap(x,y); 23 for (int j=N;j>=0;j--) 24 if (deep[x]<deep[y] && deep[fa[y][j]]>=deep[x]) y=fa[y][j]; 25 if (x==y) return x; 26 for (int j=N;j>=0;j--) 27 if (fa[x][j]!=fa[y][j]){ 28 x=fa[x][j];y=fa[y][j]; 29 } 30 return fa[x][0]; 31 } 32 int query(int x,int y,int fa1,int fa2,int l,int r,int kk){ 33 if (l==r) return l; 34 int mid=(l+r)>>1; 35 int tmp=tree[tree[x].l].num+tree[tree[y].l].num-tree[tree[fa1].l].num-tree[tree[fa2].l].num; 36 if (tmp>=kk) return query(tree[x].l,tree[y].l,tree[fa1].l,tree[fa2].l,l,mid,kk); 37 else return query(tree[x].r,tree[y].r,tree[fa1].r,tree[fa2].r,mid+1,r,kk-tmp); 38 } 39 void dfs(int x,int faa){ 40 int dex=lower_bound(refl+1,refl+1+tot,a[x])-refl; 41 update(root[x],root[faa],1,tot,dex); 42 fa[x][0]=faa; deep[x]=deep[faa]+1; 43 for (int i=1;(1<<i)<=deep[x];i++) 44 fa[x][i]=fa[fa[x][i-1]][i-1]; 45 for (int i=head[x];i!=-1;i=edge[i].nxt){ 46 int tmp=edge[i].to; 47 if (tmp==faa) continue; 48 dfs(tmp,x); 49 } 50 } 51 void init(int n){ 52 for (int i=0;i<=n;i++) head[i]=-1; 53 num=0;size=0;deep[0]=0; 54 N=floor(log(1.0*n)/log(2.0)); 55 } 56 int main(){ 57 int n,m,x,y,k;scanf("%d%d",&n,&m); 58 init(n); 59 for (int i=1;i<=n;i++){ 60 scanf("%d",&a[i]); 61 refl[i]=a[i]; 62 } 63 sort(refl+1,refl+1+n); 64 tot=unique(refl+1,refl+1+n)-(refl+1); 65 for (int i=1;i<=n-1;i++){ 66 scanf("%d%d",&x,&y); 67 add(x,y); add(y,x); 68 } 69 dfs(1,0); 70 int Lans=0; 71 while(m--){ 72 scanf("%d%d%d",&x,&y,&k); 73 x^=Lans; int _lca=LCA(x,y); 74 int tmp=query(root[x],root[y],root[_lca],root[fa[_lca][0]],1,tot,k); 75 printf("%d\n",Lans=refl[tmp]); 76 } 77 return 0; 78 }
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+10; 4 struct node{ 5 int to,nxt; 6 }edge[maxn*2]; 7 struct node2{ 8 int l,r,num; 9 }tree[maxn*70]; 10 int num=0,size=0,N,tot,a[maxn],refl[maxn],head[maxn],fa[maxn][30],deep[maxn],root[maxn]; 11 void add(int x,int y){ 12 edge[++num]={y,head[x]};head[x]=num; 13 } 14 void update(int &x,int y,int l,int r,int dex){ 15 x=++size;tree[x]=tree[y];tree[x].num++; 16 if (l==r) return ; 17 int mid=(l+r)>>1; 18 if (dex<=mid) update(tree[x].l,tree[y].l,l,mid,dex); 19 else update(tree[x].r,tree[y].r,mid+1,r,dex); 20 } 21 int LCA(int x,int y){ 22 if (deep[x]>deep[y]) swap(x,y); 23 for (int j=N;j>=0;j--) 24 if (deep[x]<deep[y] && deep[fa[y][j]]>=deep[x]) y=fa[y][j]; 25 if (x==y) return x; 26 for (int j=N;j>=0;j--) 27 if (fa[x][j]!=fa[y][j]){ 28 x=fa[x][j];y=fa[y][j]; 29 } 30 return fa[x][0]; 31 } 32 int query(int x,int y,int fa1,int fa2,int l,int r,int kk){ 33 if (l==r) return l; 34 int mid=(l+r)>>1; 35 int tmp=tree[tree[x].l].num+tree[tree[y].l].num-tree[tree[fa1].l].num-tree[tree[fa2].l].num; 36 if (tmp>=kk) return query(tree[x].l,tree[y].l,tree[fa1].l,tree[fa2].l,l,mid,kk); 37 else return query(tree[x].r,tree[y].r,tree[fa1].r,tree[fa2].r,mid+1,r,kk-tmp); 38 } 39 void dfs(int x,int faa){ 40 int dex=lower_bound(refl+1,refl+1+tot,a[x])-refl; 41 update(root[x],root[faa],1,tot,dex); 42 fa[x][0]=faa; deep[x]=deep[faa]+1; 43 for (int i=1;(1<<i)<=deep[x];i++) 44 fa[x][i]=fa[fa[x][i-1]][i-1]; 45 for (int i=head[x];i!=-1;i=edge[i].nxt){ 46 int tmp=edge[i].to; 47 if (tmp==faa) continue; 48 dfs(tmp,x); 49 } 50 } 51 void init(int n){ 52 for (int i=0;i<=n;i++) head[i]=-1; 53 num=0;size=0;deep[0]=0; 54 N=floor(log(1.0*n)/log(2.0)); 55 } 56 int main(){ 57 int n,m,x,y,k;scanf("%d%d",&n,&m); 58 init(n); 59 for (int i=1;i<=n;i++){ 60 scanf("%d",&a[i]); 61 refl[i]=a[i]; 62 } 63 sort(refl+1,refl+1+n); 64 tot=unique(refl+1,refl+1+n)-(refl+1); 65 for (int i=1;i<=n-1;i++){ 66 scanf("%d%d",&x,&y); 67 add(x,y); add(y,x); 68 } 69 dfs(1,0); 70 int Lans=0; 71 while(m--){ 72 scanf("%d%d%d",&x,&y,&k); 73 x^=Lans; int _lca=LCA(x,y); 74 int tmp=query(root[x],root[y],root[_lca],root[fa[_lca][0]],1,tot,k); 75 printf("%d\n",Lans=refl[tmp]); 76 } 77 return 0; 78 }
PS。bzoj2588卡内存,主席树开*70就过了。