zoukankan      html  css  js  c++  java
  • bzoj2588: Spoj 10628. Count on a tree 主席树

    在每一个点的父亲做主席树,每次访问时用两个点的和减去其LCA和LCA父亲的和即可。

    #include<bits/stdc++.h>
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
    int q[101000],a[101000],fa[101000],n,m,len=0,dd,lin[101000],cnt=0,p[100100][23],hash[101000],l[2500000],r[2500000],sum[2500000],d[101000],root[101000];
    bool f[101000];
    struct one
    {
        int y,next;
    };
    one e[201000];
    void insert(int xx,int yy)
    {
        e[++len].next=lin[xx];
        lin[xx]=len;
        e[len].y=yy;
    }
    int maketree(int L,int R)
    {
        int rt=++len;
        sum[rt]=0;
        if(L<R)
        {
            int mid=(L+R)>>1;
            l[rt]=maketree(L,mid);
            r[rt]=maketree(mid+1,R);
        }
        return rt;
    }
    int lca(int x,int y)
    {
        if(d[x]>d[y])swap(x,y);
        int ff=d[y]-d[x];
        for(int i=0;(1<<i)<=n;i++)
        {
            if((1<<i)&ff)y=p[y][i];
        }
        if(x==y)return x;
        for(int i=log2(n);i>=0;i--)
            if(p[x][i]!=p[y][i]){x=p[x][i];y=p[y][i];}
        x=p[x][0];
        return x;
    }
    int update(int pre,int L,int R,int x)
    {
        int rt=++len;
        sum[rt]=sum[pre]+1;l[rt]=l[pre];r[rt]=r[pre];
        if(L<R)
        {
            int mid=(L+R)>>1;
            if(x<=mid)l[rt]=update(l[pre],L,mid,x);
            else r[rt]=update(r[pre],mid+1,R,x);
        }
        return rt;
    }
    void init()
    {
        q[1]=1;int head=0,tail=1;
        f[1]=true;
        while(head++<tail)
        {
            int tn=q[head];int x=lower_bound(hash+1,hash+dd+1,a[tn])-hash;
            root[tn]=update(root[fa[tn]],1,dd,x);
            for(int i=lin[tn];i;i=e[i].next)
            {
                if(f[e[i].y])continue;
                f[e[i].y]=true;fa[e[i].y]=tn;
                p[e[i].y][0]=tn;
                d[e[i].y]=d[tn]+1;
                q[++tail]=e[i].y;
            }
        }
        for(int i=1;i<=22;i++)
        {
            for(int j=1;j<=n;j++)
            {
                p[j][i]=p[p[j][i-1]][i-1];
            }
        }
    }
     
    int query(int x,int y,int LCA,int faLCA,int L,int R,int k)
    {
        int f1=sum[l[x]]-sum[l[faLCA]]+sum[l[y]]-sum[l[LCA]];
        if(L>=R)return L;
        int mid=(L+R)>>1;
        if(k<=f1)return query(l[x],l[y],l[LCA],l[faLCA],L,mid,k);
        else return query(r[x],r[y],r[LCA],r[faLCA],mid+1,R,k-f1);
    }
    int work(int x,int y,int k)
    {
        int LCA=lca(x,y);
        return query(root[x],root[y],root[LCA],root[fa[LCA]],1,dd,k);
    }
    int main()
    {
        //freopen("xf.in","r",stdin);
        //freopen("xf.out","w",stdout);
        n=read();m=read();
        int x,y,k;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            hash[i]=a[i];
        }
        for(int i=1;i<n;i++)
        {
            x=read();y=read();
            insert(x,y);insert(y,x);
        }
        len=0;
        sort(hash+1,hash+n+1);
        dd=unique(hash+1,hash+n+1)-hash-1;
        root[0]=maketree(1,dd);
        init();
        int ans=0;
        for(int i=1;i<m;i++)
        {
            x=read();
            x^=ans;
            y=read();
            k=read();
            ans=hash[work(x,y,k)];
            printf("%d
    ",ans);
        }
        x=read();
            x^=ans;
            y=read();
            k=read();
            ans=hash[work(x,y,k)];
            printf("%d",ans);
        return 0;
    }
    

      注意最后一行不换行。

  • 相关阅读:
    ALV实时刷新功能的实现
    sap中批量导入Excel表格中的数据
    从se11新建的表维护中,给维护的数据做限制处理,例如,只允许输入vp开头的数据
    abap之ranges使用
    Abap中LOOP循环时使用AT FIRST. 传数过程中出现一串 ******** ------解决办法
    Django项目-创建第一个页面
    Python3创建django项目
    Python3安装Pyyaml
    Appium命令行环境搭建及参数使用
    c# ABP 中开启新的事务
  • 原文地址:https://www.cnblogs.com/mybing/p/8548867.html
Copyright © 2011-2022 走看看