• bzoj 2588: Spoj 10628. Count on a tree【主席树+倍增】


    算是板子,把值离散化,每个点到跟上做主席树,然后查询的时候主席树上用u+v-lca-fa[lca]的值二分

    #include<iostream>
    #include<cstdio>
    #include<map>
    #include<algorithm>
    using namespace std;
    const int N=100005;
    int n,m,h[N],cnt,tot,la,a[N],ha[N],b[N],has,f[N][30],rt[N],ind,po[N],nu[N],de[N];
    map<int,int>mp;
    struct qwe
    {
        int ne,to;
    }e[N<<1];
    struct zhuxishu
    {
        int ls,rs,sum;
    }t[2200005];
    int read()
    {
        int r=0,f=1;
        char p=getchar();
        while(p>'9'||p<'0')
        {
            if(p=='-')
                f=-1;
            p=getchar();
        }
        while(p>='0'&&p<='9')
        {
            r=r*10+p-48;
            p=getchar();
        }
        return r*f;
    }
    void add(int u,int v)
    {
        cnt++;
        e[cnt].ne=h[u];
        e[cnt].to=v;
        h[u]=cnt;
    }
    void dfs(int u,int fat)
    {
        f[u][0]=fat;
        nu[++ind]=u;
        po[u]=ind;
        de[u]=de[fat]+1;
        for(int i=h[u];i;i=e[i].ne)
            if(e[i].to!=fat)
                dfs(e[i].to,u);
    }
    void update(int l,int r,int pr,int &ro,int w)
    {
        ro=++tot;
        t[ro].sum=t[pr].sum+1;
        if(l==r)
            return;
        t[ro].ls=t[pr].ls;
        t[ro].rs=t[pr].rs;
        int mid=(l+r)>>1;
        if(w<=mid)
            update(l,mid,t[pr].ls,t[ro].ls,w);
        else
            update(mid+1,r,t[pr].rs,t[ro].rs,w);
    }
    int lca(int x,int y)
    {
        if(de[x]<de[y])
            swap(x,y);
        for(int i=16;i>=0;i--)
            if((1<<i)&(de[x]-de[y]))
                x=f[x][i];
        for(int i=16;i>=0;i--)
            if(f[x][i]!=f[y][i])
                x=f[x][i],y=f[y][i];
        return x==y?x:f[x][0];
    }
    int ques(int x,int y,int k)
    {
        int a=x,b=y,c=lca(a,b),d=f[c][0];
        a=rt[po[a]],b=rt[po[b]],c=rt[po[c]],d=rt[po[d]];
        int l=1,r=has;
        while(l<r)
        {
            int mid=(l+r)>>1;
            int now=t[t[a].ls].sum+t[t[b].ls].sum-t[t[c].ls].sum-t[t[d].ls].sum;
            if(now>=k)
            {
                r=mid;
                a=t[a].ls,b=t[b].ls,c=t[c].ls,d=t[d].ls;
            }
            else
            {
                k-=now;
                l=mid+1;
                a=t[a].rs,b=t[b].rs,c=t[c].rs,d=t[d].rs;
            }
        }
        return ha[l];
    }
    int main()
    {
        n=read(),m=read();
        for(int i=1;i<=n;i++)
            a[i]=read(),b[i]=a[i];
        sort(b+1,b+1+n);
        for(int i=1;i<=n;i++)
            if(i==1||b[i]!=b[i-1])
                mp[b[i]]=++has,ha[has]=b[i];
        for(int i=1;i<=n;i++)
            a[i]=mp[a[i]];
        for(int i=1;i<n;i++)
        {
            int x=read(),y=read();
            add(x,y);add(y,x);
        }
        dfs(1,0);
        for(int j=1;j<=16;j++)
            for(int i=1;i<=n;i++)
                f[i][j]=f[f[i][j-1]][j-1];
        for(int i=1;i<=n;i++)
            update(1,has,rt[po[f[nu[i]][0]]],rt[i],a[nu[i]]);
        for(int i=1;i<=m;i++)
        {
            int x=read(),y=read(),k=read();
            x^=la;
            la=ques(x,y,k);
            printf("%d",la);
            if(i!=m)
                puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    知识点复习
    【程序人生】一个IT人的立功,立言,立德三不朽
    【朝花夕拾】Android多线程之(三)runOnUiThread篇——程序猿们的贴心小棉袄
    【朝花夕拾】Android多线程之(二)ThreadLocal篇
    【朝花夕拾】Android多线程之(一)View.post()篇
    Camera2笔记
    HangFire多集群切换及DashBoard登录验证
    Linq 动态多条件group by
    Api接口签名验证
    postgre ||连接字段
  • 原文地址:https://www.cnblogs.com/lokiii/p/9719181.html
Copyright © 2020-2023  润新知