「题解」:$e$

问题 B: $e$

时间限制: 2 Sec  内存限制: 512 MB

题面


题面谢绝公开。

题解


话说一天考两个主席树这回事……

正解可以叫树上主席树??(脸哥说也叫主席树上树???)

对于树上的每一条链建主席树,支持链上查询前驱和后继。

对于所有的$p[i]$,他说怎么得到就按他说的做就好,然后求所有$p[i]$的$LCA$。

对于每个$p[i]$到$LCA$的链上查一次$r$的前驱和后继更新答案即可。

注意:参数不要传反、别一个特判把自己判掉、pre和nxt的代码不要粘贴,粘贴了不要忘记改掉内部递归函数……

(昨天下午大概帮3、4个人调这题代码???RP++)

#include
#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;ii)
        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);
    }
}
View Code

你可能感兴趣的:(「题解」:$e$)