zoukankan      html  css  js  c++  java
  • 主席树——树链上第k大spoj COT

    首先要求第k大就想到用主席树来处理

    但是不能直接用树链剖分的dfs序来维护,因为一条链对应的dfs下标可能是断开的几段,无法用权值线段树来维护

    那么久维护每个点到根节点的全值线段树,结点u的权值线段树记录了其到根节点路径上数值的出现次数

    主席树相当于维护了一个前缀和,由树上前缀和可以分析出u->v路径上对应的那棵权值线段树应该是

      T[u]+T[v]-T[lca]-T[fa[lca]]

    所以只要在dfs过程中,结点u依赖fa[u]进行更新主席树即可

    那么问题解变成了每个结点u上维护到root的权值线段树,然后每次询问求lca(u,v),再按照上述公式去主席树上查询第k大

    求lca可以用树剖,也可以倍增。。

    #include <bits/stdc++.h>
    #define maxn 100005
    using namespace std;
    const int N = 1e5+100;
    struct Node{int lc,rc,sum;}T[N*20];
    int fa[2*N][30], dep[2*N], vis[N];
    int a[N], b[N], tot, cnt, head[N], len;
    struct node{int to, next;} p[2*N];
    void init(){
        memset(head,-1,sizeof(head));
        memset(vis,0,sizeof(vis));
        cnt=0;
        return ;
    }
    void add(int u,int v){
        p[cnt].to=v,p[cnt].next=head[u];head[u]=cnt++;
        p[cnt].to=u,p[cnt].next=head[v];head[v]=cnt++;
        return ;
    }
    int size,rt[N];
    int build(int l,int r){
        int now=++size;
        T[now].lc=T[now].rc=T[now].sum=0;
        if(l==r)return now;
        int mid=l+r>>1;
        T[now].lc=build(l,mid);
        T[now].rc=build(mid+1,r); 
        return now;
    }
    
    int update(int l,int r,int last,int pos){//更新到pos点 
        int now=++size;
         T[now]=T[last];T[now].sum++;
         if(l==r)return now;
         int mid=l+r>>1;
         if(pos<=mid)T[now].lc=update(l,mid,T[last].lc,pos);
         else T[now].rc=update(mid+1,r,T[last].rc,pos);
         return now;
    }
    int query(int e1,int e2,int s1,int s2,int l,int r,int k){
        if(l==r)return l;
        int mid=l+r>>1;
        int sum=T[T[e1].lc].sum+T[T[e2].lc].sum-T[T[s1].lc].sum-T[T[s2].lc].sum;
        if(k<=sum)return query(T[e1].lc,T[e2].lc,T[s1].lc,T[s2].lc,l,mid,k);
        else return query(T[e1].rc,T[e2].rc,T[s1].rc,T[s2].rc,mid+1,r,k-sum);
    }
    
    void dfs(int u,int d,int f,int root){
        vis[u]=1,dep[u]=d,fa[u][0]=f;
        rt[u]=update(1,len,root,a[u]);
        for(int i=head[u];i!=-1;i=p[i].next){
            int v=p[i].to;
            if(vis[v]) continue;
            dfs(v,d+1,u,rt[u]);
        }
    }
    
    int f[maxn],son[maxn],d[maxn],siz[maxn];
    void dfs1(int x,int pre,int deep){
        f[x]=pre;siz[x]=1;d[x]=deep;
        for(int i=head[x];i!=-1;i=p[i].next){
            int y=p[i].to;
            if(y==pre)continue;
            dfs1(y,x,deep+1);
            siz[x]+=siz[y];
            if(siz[y]>siz[son[x]])son[x]=y;
        }
    }
    int id[maxn],rk[maxn],idx,top[maxn];
    void dfs2(int x,int tp){
        top[x]=tp;id[x]=++idx;rk[idx]=x;
        if(son[x])dfs2(son[x],tp);
        for(int i=head[x];i!=-1;i=p[i].next){
            int y=p[i].to;
            if(y!=son[x] && y!=f[x])dfs2(y,y);
        }
    }
    int Query(int x,int y){
        while(top[x]!=top[y]){
            if(d[top[x]]<d[top[y]])swap(x,y);
            x=f[top[x]];
        }
        if(id[x]>id[y])swap(x,y);
        return x;
    }
     
    int main(){
        int t, n, q;
        scanf("%d %d", &n, &q);
        for(int i=1; i<=n; i++) scanf("%d", &a[i]), b[i]=a[i];
        sort(b+1,b+n+1);
        len=unique(b+1,b+n+1)-(b+1);
        tot=0;
        rt[0]=build(1,len);
        for(int i=1; i<=n; i++)  a[i]=lower_bound(b+1,b+len+1,a[i])-(b);
        init();
        for(int i=0;i<n-1;i++){
            int x, y;
            scanf("%d %d", &x, &y);
            add(x,y);
        }
        dfs(1,1,0,rt[0]);dfs1(1,0,1),dfs2(1,1);
        int ans=0;
        while(q--){
            int l, r, x;
            scanf("%d %d %d", &l, &r, &x);l^=ans;
            int pos=Query(l,r);
            printf("%d
    ",ans=b[query(rt[l],rt[r],rt[pos],rt[fa[pos][0]],1,len,x)]);
        }
        return 0;
    }
  • 相关阅读:
    Oracle数据库的一些常用命令
    计算机网络:计算路由表下一跳
    怎样快速对二进制和十进制进行互转化——IP地址规划与设计总结
    计算机网络-以太网,局域网,城域网,广域网,互联网,因特网,万维网的区分
    Apache与Tomcat有什么关系和区别
    Oracle 添加用户并赋权,修改密码,解锁,删除用户的方法
    使用Oracle的PROFILE对用户资源限制和密码限制
    通过修改profile 来修改账号的过期时间
    解决oracle用户过期问题
    【项目】项目36
  • 原文地址:https://www.cnblogs.com/zsben991126/p/10762819.html
Copyright © 2011-2022 走看看