问题 B: e
时间限制: 2 Sec 内存限制: 512 MB
题面
题面谢绝公开。
题解
话说一天考两个主席树这回事……
正解可以叫树上主席树??(脸哥说也叫主席树上树???)
对于树上的每一条链建主席树,支持链上查询前驱和后继。
对于所有的$p[i]$,他说怎么得到就按他说的做就好,然后求所有$p[i]$的$LCA$。
对于每个$p[i]$到$LCA$的链上查一次$r$的前驱和后继更新答案即可。
注意:参数不要传反、别一个特判把自己判掉、pre和nxt的代码不要粘贴,粘贴了不要忘记改掉内部递归函数……
(昨天下午大概帮3、4个人调这题代码???RP++)

#include<bits/stdc++.h>
#define rint register int
using namespace std;
const int N=100005,M=1000000000;
inline void read(int &A)
{
A=0;int B=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')B=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){A=(A<<3)+(A<<1)+ch-'0';ch=getchar();}
A=A*B;
}
int n,q,tp,ans,a[N],p[N];
int v[N<<1],nxt[N<<1],first[N<<1],tot;
int root[N],ls[N<<6],rs[N<<6],val[N<<6],cnt;
int dep[N],f[N][23];
inline void build_line(int uu,int vv)
{
v[++tot]=vv,nxt[tot]=first[uu];
first[uu]=tot;return ;
}
inline void insert(int &k,int l,int r,int his,int dat)
{
k=++cnt;val[k]=val[his]+1;
if(l==r)return ;
ls[k]=ls[his],rs[k]=rs[his];
int mid=(l+r)>>1;
if(dat<=mid)insert(ls[k],l,mid,ls[his],dat);
else insert(rs[k],mid+1,r,rs[his],dat);
}
inline int get_pre(int k1,int k2,int l,int r,int dat)
{
if(!(val[k2]-val[k1]))return 0;
if(l==r)return l;int mid=(l+r)>>1;
if(dat<=mid)return get_pre(ls[k1],ls[k2],l,mid,dat);
int lin=get_pre(rs[k1],rs[k2],mid+1,r,dat);
if(!lin)return get_pre(ls[k1],ls[k2],l,mid,dat);
return lin;
}
inline int get_nxt(int k1,int k2,int l,int r,int dat)
{
if(!(val[k2]-val[k1]))return 0;
if(l==r)return l;int mid=(l+r)>>1;
if(dat>mid)return get_nxt(rs[k1],rs[k2],mid+1,r,dat);
int lin=get_nxt(ls[k1],ls[k2],l,mid,dat);
if(!lin)return get_nxt(rs[k1],rs[k2],mid+1,r,dat);
return lin;
}
inline void bfs()
{
queue <int> q;
q.push(1);dep[1]=1;
while(!q.empty())
{
int x=q.front();q.pop();
for(rint i=first[x];i;i=nxt[i])
{
int y=v[i];if(dep[y])continue;
dep[y]=dep[x]+1;f[y][0]=x;
for(rint i=1;i<=20;++i)
f[y][i]=f[f[y][i-1]][i-1];
q.push(y);
}
}
return ;
}
inline int get_lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
for(rint i=20;i>=0;--i)
if(dep[f[x][i]]>=dep[y])x=f[x][i];
if(x==y)return x;
for(rint i=20;i>=0;--i)
if(f[x][i]!=f[y][i])
x=f[x][i],y=f[y][i];
return f[x][0];
}
inline void dfs_build(int x,int fa)
{
insert(root[x],1,M,root[fa],a[x]);
for(rint i=first[x];i;i=nxt[i])
if(v[i]!=fa)dfs_build(v[i],x);
return ;
}
int main()
{
read(n),read(q),read(tp);
for(rint i=1;i<=n;++i)read(a[i]);
for(rint i=1,ST,EN;i<n;++i)
read(ST),read(EN),build_line(ST,EN),build_line(EN,ST);
dfs_build(1,0);bfs();
for(rint i=1,r,k;i<=q;++i)
{
read(r),read(k);
for(rint j=1,x;j<=k;++j)
read(x),p[j]=(x-1+ans*tp)%n+1;
int lca=p[1];
for(rint j=2;j<=k;++j)
lca=get_lca(lca,p[j]);
ans=0x7fffffff;
for(rint j=1;j<=k;++j)
{
int pre=get_pre(root[f[lca][0]],root[p[j]],1,M,r);
int nxt=get_nxt(root[f[lca][0]],root[p[j]],1,M,r);
if(pre)ans=min(r-pre,ans);
if(nxt)ans=min(nxt-r,ans);
}
printf("%d\n",ans);
}
}
