Count on a tree
给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
N,M<=100000
题解
一开始看了标签:嗯,主席树。那么一定就要放在序列上搞,dfs序。然后又是一条链,树链剖分,每次提取log个区间出来,就像树状数组套主席树一样。
然后就re了。
嗯,上界开小了,离散化。
T了。 (破案了,储存查询的主席树的根的数组没清空)
题解:树上差分,维护点到根的主席树,维护四个根即可x,y,lca,fa[lca]。
然后就A了。
#include<map> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define re register const int maxn=100005; int n,m,a[maxn]; int cnt,head[maxn]; int fa[maxn][21],dep[maxn]; int root[maxn],ls[maxn*50],rs[maxn*50],sum[maxn*50]; struct edge{ int x,y,next; }e[maxn<<1]; template<class T>inline void read(T &x){ x=0;int f=0;char ch=getchar(); while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x = f ? -x : x ; } void write(int x){ if(x>9) write(x/10); putchar(x%10+'0'); } void add(int x,int y){ e[++cnt]=(edge){x,y,head[x]}; head[x]=cnt; } void copy(int x,int y){ls[x]=ls[y];rs[x]=rs[y];sum[x]=sum[y];} int build(int rt,int l,int r,int pos){ int t=++cnt; copy(t,rt); sum[t]++; if(l==r) return t; int mid=(l+r)>>1; if(pos<=mid) ls[t]=build(ls[t],l,mid,pos); else rs[t]=build(rs[t],mid+1,r,pos); return t; } void dfs(int x){ root[x]=build(root[fa[x][0]],1,n,a[x]); for(int i=1;i<=20;i++) fa[x][i]=fa[fa[x][i-1]][i-1]; for(int i=head[x];i;i=e[i].next){ int y=e[i].y; if(y==fa[x][0]) continue; fa[y][0]=x; dep[y]=dep[x]+1; dfs(y); } } int lca(int x,int y){ if(dep[x]>dep[y]) swap(x,y); int delt=dep[y]-dep[x]; for(int i=0;delt;i++,delt>>=1) if(delt&1) y=fa[y][i]; if(x==y) return x; for(int i=20;fa[x][0]!=fa[y][0];i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int query(int x1,int x2,int y1,int y2,int k){ int l=1,r=n; while(1){ if(l==r) return l; int ret=sum[ls[x1]]+sum[ls[x2]]-sum[ls[y1]]-sum[ls[y2]],mid=(l+r)>>1; if(ret>=k){ x1=ls[x1];x2=ls[x2];y1=ls[y1];y2=ls[y2]; r=mid; } else { x1=rs[x1];x2=rs[x2];y1=rs[y1];y2=rs[y2]; l=mid+1;k-=ret; } } } inline int query(int x,int y,int k){ int t=lca(x,y); return query(root[x],root[y],root[t],root[fa[t][0]],k); } int tot,b[maxn],cx[maxn]; int main(){ read(n);read(m); for(re int i=1;i<=n;i++) read(a[i]),b[++tot]=a[i]; sort(b+1,b+n+1); tot=unique(b+1,b+tot+1)-b-1; for(re int i=1;i<=n;++i){ int x=lower_bound(b+1,b+tot+1,a[i])-b; cx[x]=a[i]; a[i]=x; } for(re int i=1;i<n;++i){ int x,y; read(x);read(y); add(x,y);add(y,x); } cnt=0; dfs(1); int ans=0; while(m--){ int x,y,k; read(x);read(y);read(k); x^=ans; write(ans=cx[query(x,y,k)]); putchar(10); } }
#include<map> #include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define re register const int maxn=100005; int n,m,a[maxn]; int cnt,head[maxn]; int fa[maxn],son[maxn],dep[maxn],size[maxn]; int aa[maxn],id[maxn],top[maxn]; int root[maxn],ls[maxn*50],rs[maxn*50],sum[maxn*50]; struct edge{ int x,y,next; }e[maxn<<1]; template<class T>inline void read(T &x){ x=0;int f=0;char ch=getchar(); while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x = f ? -x : x ; } void write(int x){ if(x>9) write(x/10); putchar(x%10+'0'); } void add(int x,int y){ e[++cnt]=(edge){x,y,head[x]}; head[x]=cnt; } void dfs(int x){ size[x]=1; for(int i=head[x];i;i=e[i].next){ int y=e[i].y; if(y==fa[x]) continue; fa[y]=x; dep[y]=dep[x]+1; dfs(y); if(size[son[x]]<size[y]) son[x]=y; size[x]+=size[y]; } } void dfs(int x,int tp){ id[x]=++cnt; aa[cnt]=a[x]; top[x]=tp; if(!son[x]) return ; dfs(son[x],tp); for(int i=head[x];i;i=e[i].next){ int y=e[i].y; if(y==fa[x]||y==son[x]) continue; dfs(y,y); } } void copy(int x,int y){ls[x]=ls[y];rs[x]=rs[y];sum[x]=sum[y];} int build(int rt,int l,int r,int pos){ int t=++cnt; copy(t,rt); sum[t]++; if(l==r) return t; int mid=(l+r)>>1; if(pos<=mid) ls[t]=build(ls[t],l,mid,pos); else rs[t]=build(rs[t],mid+1,r,pos); return t; } int tp1,tp2,s1[maxn],s2[maxn]; inline int query(int k){ int l=0,r=n; while(1){ if(l==r) return l; int ret=0,mid=(l+r)>>1; for(re int i=1;i<=tp1;++i) ret+=sum[ls[s2[i]]]-sum[ls[s1[i]]]; if(ret>=k){ for(re int i=1;i<=tp1;++i) s1[i]=ls[s1[i]],s2[i]=ls[s2[i]]; r=mid; } else { for(re int i=1;i<=tp1;++i) s1[i]=rs[s1[i]],s2[i]=rs[s2[i]]; l=mid+1;k-=ret; } } } inline int query(int x,int y,int k){ tp1=tp2=0; while(top[x]!=top[y]){ if(dep[top[x]]>dep[top[y]]) swap(x,y); s1[++tp1]=root[id[top[y]]-1]; s2[++tp2]=root[id[y]]; y=fa[top[y]]; } if(dep[x]>dep[y]) swap(x,y); s1[++tp1]=root[id[x]-1]; s2[++tp2]=root[id[y]]; return query(k); } int tot,b[maxn],cx[maxn]; int main(){ read(n);read(m); for(re int i=1;i<=n;i++) read(a[i]),b[++tot]=a[i]; sort(b+1,b+n+1); tot=unique(b+1,b+tot+1)-b-1; for(re int i=1;i<=n;++i){ int x=lower_bound(b+1,b+tot+1,a[i])-b; cx[x]=a[i]; a[i]=x; } for(re int i=1;i<n;++i){ int x,y; read(x);read(y); add(x,y);add(y,x); } cnt=0; dfs(1); dfs(1,1); for(re int i=1;i<=n;++i) root[i]=build(root[i-1],0,n,aa[i]); int ans=0; while(m--){ int x,y,k; read(x);read(y);read(k); x^=ans; write(ans=cx[query(x,y,k)]); putchar(10); } }
然后关于静态k大