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

    主席树。

    求a到b的路径可以看作a到根和b到根的路径的一部分。

    对于每个节点,需要查询它到根路径各个数出现的次数。

    如果对于每个节点都建一棵权值线段树,肯定会爆掉。

    这时用主席树,该节点的权值线段树由父亲的权值线段树转移而来。

    建树之前,要对整个数进行重标号,建树的时候才能保证父亲的树已经被建了。

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    const int maxd = 18;
    const int maxn = 100000 + 10;
    const int maxm = 200000 + 10;
    const int maxx = 4000000 + 10;
    
    int n,m,q,la,cnt,size;
    int g[maxn],v[maxm],next[maxm],eid;
    int anc[maxn][maxd+5];
    int h[maxn];
    int num[maxn],pos[maxn];
    int lc[maxx],rc[maxx],s[maxx];
    int a[maxn],t[maxn];
    int root[maxn];
    
    void addedge(int a,int b) {
        v[eid]=b; next[eid]=g[a]; g[a]=eid++;
        v[eid]=a; next[eid]=g[b]; g[b]=eid++;    
    }
    
    void dfs(int u) {
        num[++cnt]=u; pos[u]=cnt;
        for(int d=1;d<maxd;d++) anc[u][d]=anc[anc[u][d-1]][d-1];
        for(int i=g[u];~i;i=next[i]) if(v[i]!=anc[u][0]) {
            anc[v[i]][0]=u;
            h[v[i]]=h[u]+1;
            dfs(v[i]);    
        }
    }
    
    int LCA(int a,int b) {
        if(h[a]<h[b]) swap(a,b);
        for(int i=maxd-1;i>=0;i--) if(h[anc[a][i]]>=h[b]) a=anc[a][i];
        if(a==b) return a;
        for(int i=maxd-1;i>=0;i--) 
            if(anc[a][i]!=anc[b][i]) {
                a=anc[a][i];
                b=anc[b][i];
            }
        return anc[a][0];
    }
    
    void modify(int &x,int y,int L,int R,int pos) {
        x=++size; s[x]=s[y]+1;
        lc[x]=lc[y],rc[x]=rc[y];
        if(L==R) return;
        
        int mid=(L+R)>>1;
        if(pos<=mid) modify(lc[x],lc[y],L,mid,pos);
        else modify(rc[x],rc[y],mid+1,R,pos);    
    }
    
    int query(int a,int b,int k) {
        int c=LCA(a,b),d=anc[c][0];
        
        a=root[pos[a]]; b=root[pos[b]]; c=root[pos[c]]; d=root[pos[d]];
        int l=1,r=m,mid,cur;
        while(l<r) { 
            mid=(l+r)>>1;
            cur=s[lc[a]]+s[lc[b]]-s[lc[c]]-s[lc[d]];
            if(k<=cur) {
                a=lc[a]; b=lc[b]; c=lc[c]; d=lc[d]; r=mid;    
            }
            else {
                a=rc[a]; b=rc[b]; c=rc[c]; d=rc[d]; l=mid+1; k-=cur;
            }
        }
        return t[l];
    }
    
    int main() {
        memset(g,-1,sizeof(g));
        scanf("%d%d",&n,&q);    
        for(int i=1;i<=n;i++) {
            scanf("%d",&a[i]);
            t[i]=a[i];
        }
        sort(t+1,t+n+1);
        m=unique(t+1,t+n+1)-(t+1);
        for(int i=1;i<=n;i++) a[i]=lower_bound(t+1,t+m+1,a[i])-t;
        for(int i=1,u,v;i<n;i++) {
            scanf("%d%d",&u,&v);
            addedge(u,v);
        }
        cnt=0; h[1]=1; anc[1][0]=0;
        dfs(1);
            
        root[0]=lc[0]=rc[0]=s[0]=0;
        for(int i=1;i<=n;i++)
            modify(root[i],root[pos[anc[num[i]][0]]],1,m,a[num[i]]);
        la=0;
        
        for(int i=1,u,v,k;i<=q;i++) {
            scanf("%d%d%d",&u,&v,&k);
            u^=la;
            printf("%d",la=query(u,v,k));
            if(i!=q) printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    括号匹配的检验
    学习过程中遇到的比较有价值的博客--整理
    Spring+SpringMVC+MyBatis的pom.xml依赖
    Hibernate内容详解
    Struts2的拦截器配置
    Maven构建Struts2项目
    Mybatis增删改查,Demo整合
    简单Java类 全网最详细讲解 !!!
    Javaoop 遇到的问题
    Bootstrap 前端框架 遇到的问题 解决方案
  • 原文地址:https://www.cnblogs.com/invoid/p/5661344.html
Copyright © 2011-2022 走看看