洛谷 2633 Count on a tree
题目是一个n个点的数,q次询问,每次询问回答一条路径上第k小数。
在树上建主席树,每个点的状态可以从父亲节点得到。
求答案时答案由路径两个端点的权值线段树之和减去lca和lca父亲节点的权值线段树之和。
因为两个端点的权值线段树之和会多算一次跟节点到lca路径上出现的权值以及根节点到lca父亲节点路径上出现的权值。
#include <bits/stdc++.h> using namespace std; const int M = 1e5+7; int n,q,tot,pos; int a[M],ls[M],sz; /************lca***************/ int cnt,head[M]; struct edge { int v,next; }e[M<<1]; void init(){ tot=cnt=0;memset(head,-1,sizeof(head)); } void add(int u,int v){ e[++cnt].v=v;e[cnt].next=head[u]; head[u]=cnt; } int f[M][22],fat[M],deep[M]; void dfs(int u,int fa,int d){ deep[u]=d; for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs(v,u,d+1); f[v][0]=u; fat[v]=u; } return ; } void work(){//RMQ for(int i=1;i<20;i++) for(int j=1;j<=n;j++) f[j][i]=f[f[j][i-1]][i-1]; } int lca(int x,int y){//lca if(deep[x]<deep[y]) swap(x,y); int dt=deep[x]-deep[y]; for(int i=0;i<20;i++) if(dt&(1<<i)) x=f[x][i]; if(x==y) return x; for(int i=19;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; } /***********************zhuxishu*******************/ int L[20*M],R[20*M],num[20*M],T[M]; void build(int l,int r,int rt){ rt=++tot; num[rt]=0; if(l==r) return; int mid=(l+r)>>1; build(l,mid,L[rt]); build(mid+1,r,R[rt]); } void update(int l,int r,int &rt,int pre){ rt=++tot; num[rt]=num[pre]+1; if(l==r) return ; L[rt]=L[pre];R[rt]=R[pre]; int mid=(l+r)>>1; if(pos<=mid) update(l,mid,L[rt],L[pre]); else update(mid+1,r,R[rt],R[pre]); } int query(int l,int r,int xrt,int yrt,int lcart,int lcafa,int k){ if(l==r) return l; int mid=(l+r)>>1,sum=num[L[xrt]]+num[L[yrt]]-num[L[lcart]]-num[L[lcafa]]; if(sum>=k) return query(l,mid,L[xrt],L[yrt],L[lcart],L[lcafa],k); else return query(mid+1,r,R[xrt],R[yrt],R[lcart],R[lcafa],k-sum); } /****************************solve**********************************/ void dfs_build(int u,int fa){ pos=lower_bound(ls+1,ls+sz+1,a[u])-ls; update(1,sz,T[u],T[fa]); for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa) continue; dfs_build(v,u); } } void solve(){ int preans=0; dfs(1,-1,0); work(); build(1,sz,T[0]); dfs_build(1,0); while(q--){ int u,v,k; scanf("%d%d%d",&u,&v,&k); u=u^preans; preans=ls[query(1,sz,T[u],T[v],T[lca(u,v)],T[fat[lca(u,v)]],k)]; printf("%d\n", preans); } } /**************************main*************************/ int main(){ freopen("1.in","r",stdin); freopen("1.out","w",stdout); init(); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d",&a[i]),ls[i]=a[i]; sort(ls+1,ls+n+1); sz=unique(ls+1,ls+n+1)-ls-1; for(int i=1;i<n;i++){ int from,to; scanf("%d%d",&from,&to); add(from,to);add(to,from); } solve(); return 0; }

浙公网安备 33010602011771号