• BZOJ 10628 Luogu 2633


    BZOJ 10628 Luogu2633——count on a tree

    题意:查询一定区间内第K小的点权。

    由于有lastans所以强制在线,这道题就相当于树上的主席树,

    树链剖分+主席树,主席树相比普通主席树有一丢丢的改变,

    root[i]不再是指向root[i-1],而是指向它在树上的父亲,

    维护的序列是它到根节点的这条路径。

    所以在求区间第k小时,可以用前缀和的思想加上lca,

    val[u]+val[v]-val[lca]-val[fa[lca]],

    得出的是lca分别到u和v的这两条路径中每个节点的数出现的次数。

    然后用二分思想,跟普通主席树一样,二分直至l==r。

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    int size[100005]={0},fa[100005]={0},son[100005]={0},top[100005],dep[100005]={0},ls[100005*20],rs[100005*20],val[100005*20],root[100005],sz,v[100005],
    head[100005*2]={0},t=0,a[100002]={0},tot=0,real[100005]={0},dfn[100005]={0},num,cnt=0,pai[100005];
    struct hh
    {int  u,v,next;
    }e[200005];
    void add(int x,int  y)
    {
        t++;
        e[t].u=x;
        e[t].v=y;
        e[t].next=head[x];
        head[x]=t;
    }
    void dfs(int now,int anc)
    {
        
        int i;
        top[now]=anc;
            tot++;
        dfn[now]=tot;
        real[tot]=now;
        if(son[now]==-1) return;
         dfs(son[now],anc);
        for(i=head[now];i!=0;i=e[i].next)
        {
            int v=e[i].v;
            if(v!=fa[now]&&v!=son[now])
            dfs(v,v);
        }
    }
    void build(int u)
    {
        size[u]=1;
        for(int i=head[u];i!=0;i=e[i].next)
        {
            int v=e[i].v;
            if(v!=fa[u])
            {
                dep[v]=dep[u]+1;
                fa[v]=u;
                build(v);
                size[u]=size[u]+size[v];
                if(son[u]==-1||size[v]>size[son[u]])
                son[u]=v;
            }
        }
    }
    int getlca(int x,int y)
    {
        while(top[x]!=top[y])
        {
            if(dep[top[x]]<dep[top[y]])
            {
                swap(x,y);
            }
            x=fa[top[x]];
        }
        if(dep[x]<dep[y])
        {
            swap(x,y);
        }
        return y;
    }
    void insert(int &p,int cmp,int x,int l,int r){
        p=++cnt;ls[p]=ls[cmp];rs[p]=rs[cmp];val[p]=val[cmp]+1;
        if(l!=r){
            int mid=(l+r)/2;
            if(x<=mid){
                insert(ls[p],ls[cmp],x,l,mid);
            }
            else{
                insert(rs[p],rs[cmp],x,mid+1,r);
            }
        }
    }
    int query(int l,int r,int k){
        int a=l,b=r,c=getlca(a,b),d=fa[c],mid,all;
        a=root[dfn[a]];b=root[dfn[b]];c=root[dfn[c]];d=root[dfn[d]];
         l=1,r=sz;
        while(l<r){
            mid=(l+r)>>1;
            all=val[ls[a]]+val[ls[b]]-val[ls[c]]-val[ls[d]];
            if(all>=k){
                r=mid;a=ls[a];b=ls[b];c=ls[c];d=ls[d];
            }
            else{
                l=mid+1;a=rs[a];b=rs[b];c=rs[c];d=rs[d];k-=all;
            }
        }
        return v[l];
    }
    void jian(int &p,int l,int r){
        p=++cnt;
        if(l!=r){
            int mid=(l+r)/2;
            jian(ls[p],l,mid);
            jian(rs[p],mid+1,r);
        }
    }
    int main()
    {
    int c,b,k,p,i,x,y,s,z,lastans=0;
        scanf("%d%d",&num,&p);
        for(i=0;i<=num*4;i++)
        son[i]=-1;
        for(i=1;i<=num;i++)
        {
            scanf("%d",&a[i]);
        }
        for(i=1;i<=num-1;i++)
        {
            scanf("%d%d",&x,&y);
            add(x,y);
            add(y,x);
        }
        dep[1]=1;
        build(1);
        dfs(1,1);
        
        for(i=1;i<=num;i++){
            v[i]=pai[i]=a[i];
        }
         sort(v+1,v+num+1);
        sz=unique(v+1,v+num+1)-v-1;
        jian(root[0],1,sz);
        for(i=1;i<=num;i++){
            pai[i] = lower_bound(v + 1, v + 1 + sz, a[i]) - v;
        }
        for(i=1;i<=num;i++){
            int t=real[i];
            insert(root[i],root[dfn[fa[t]]],pai[t],1,sz);
        }
        while(p--){
            scanf("%d%d%d",&c,&b,&k);
            c=c^lastans;
            lastans=query(c,b,k);
            printf("%d
    ",lastans);
        }
        return 0;
    }
    BZOJ 10628 Luogu 2633

     

     

     

  • 相关阅读:
    firefox安装教程
    shell脚本介绍
    vue 图片引入
    vscode 常用插件
    vscode 打不开chrome浏览器解决方案
    win10 wifi 密码查看
    爽文 主角如 石昊 白小纯 方行 秦牧 楚风
    codepen, jsrun 使用iframe嵌入
    uniapp 自定义扫一扫页面
    数组(遍历删除多个元素)
  • 原文地址:https://www.cnblogs.com/Fish-/p/8253440.html
Copyright © 2020-2023  润新知