zoukankan      html  css  js  c++  java
  • luoguP6071 [MdOI2020] Treequery DFS序+主席树

    思路自然的码农题.        

    显然分类讨论一下编号在 $[l,r]$ 的点与 $p$ 的子树关系.        

    如果都在 $p$ 的子树内就是个区间 $lca$.  

    否则,就二分第一个满足 $p$ 的祖先且子树内部没有 $[l,r]$ 之间的点.         

    二分验证的话要用主席树. 

    code: 

    #include <cstring>   
    #include <map>
    #include <algorithm> 
    #include <cstdio> 
    #include <vector>
    #define N 200008 
    #define ll long long 
    #define setIO(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)    
    using namespace std; 
    namespace seg
    {          
        int tot;  
        int newnode() { return ++tot; }   
        struct data 
        { 
            int sum,ls,rs; 
        }s[N*50]; 
        void build(int &x,int l,int r) 
        {
            x=newnode(); 
            if(l==r) return;
            int mid=(l+r)>>1;      
            build(s[x].ls,l,mid),build(s[x].rs,mid+1,r);    
        }           
        int update(int x,int l,int r,int p,int v) 
        {
            int now=newnode();   
            s[now]=s[x],s[now].sum=s[x].sum+v;    
            if(l==r) return now;   
            int mid=(l+r)>>1;    
            if(p<=mid) s[now].ls=update(s[x].ls,l,mid,p,v); 
            else s[now].rs=update(s[x].rs,mid+1,r,p,v);     
            return now;   
        }
        int query(int x,int y,int l,int r,int L,int R) 
        {
            if(x+y==0) return 0;        
            if(l>=L&&r<=R) return s[y].sum-s[x].sum;   
            int re=0,mid=(l+r)>>1;          
            if(L<=mid)  re+=query(s[x].ls,s[y].ls,l,mid,L,R); 
            if(R>mid)   re+=query(s[x].rs,s[y].rs,mid+1,r,L,R);     
            return re;   
        }            
    };   
    int n,edges,tim;   
    int hd[N],to[N<<1],nex[N<<1],val[N<<1];  
    int fa[18][N],dfn[N],st[N],ed[N],rt[N],ge[N],dep[N],dis[N];              
    void add(int u,int v,int c) 
    { 
        nex[++edges]=hd[u],hd[u]=edges,to[edges]=v,val[edges]=c;     
    }      
    void dfs(int u,int ff) 
    {      
        st[u]=dfn[u]=++tim,ge[tim]=u;    
        fa[0][u]=ff;       
        for(int i=1;i<18;++i) fa[i][u]=fa[i-1][fa[i-1][u]];      
        for(int i=hd[u];i;i=nex[i]) 
        {
            int v=to[i]; 
            if(v==ff) continue;     
            dep[v]=dep[u]+1,dis[v]=dis[u]+val[i];    
            dfs(v,u); 
        }
        ed[u]=tim;   
    }              
    int get_lca(int x,int y) 
    {               
        if(dep[x]!=dep[y]) 
        {
            if(dep[x]>dep[y]) swap(x,y);       
            for(int i=17;i>=0;--i) if(dep[fa[i][y]]>=dep[x]) y=fa[i][y];     
        }    
        if(x==y) return x;       
        for(int i=17;i>=0;--i) if(fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y];  
        return fa[0][x];     
    }
    struct node 
    {
        int key;     
        node() { key=0; }       
        node operator+(const node &b) const 
        {
            node c;    
            c.key=get_lca(key,b.key);   
            return c;   
        }
    }tree[N<<2];    
    void build(int l,int r,int now) 
    {
        if(l==r) { tree[now].key=l; return; } 
        int mid=(l+r)>>1;   
        build(l,mid,now<<1),build(mid+1,r,now<<1|1);    
        tree[now]=tree[now<<1]+tree[now<<1|1];  
    }
    node query(int l,int r,int now,int L,int R) 
    {
        if(l>=L&&r<=R) return tree[now];    
        int mid=(l+r)>>1;   
        if(L<=mid&&R>mid) return query(l,mid,now<<1,L,R)+query(mid+1,r,now<<1|1,L,R); 
        else if(L<=mid)  return query(l,mid,now<<1,L,R); 
        else return query(mid+1,r,now<<1|1,L,R);    
    } 
    int calc(int p,int L,int R) 
    {    
        if(seg::query(rt[st[p]-1],rt[ed[p]],1,n,L,R)==R-L+1) 
            return dis[query(1,n,1,L,R).key]-dis[p];          
        else if((p>=L&&p<=R)||(seg::query(rt[st[p]-1],rt[ed[p]],1,n,L,R))) return 0;      
        else 
        {  
            int x=p;   
            // printf("qaq
    ");  
            for(int i=17;i>=0;--i) 
            {   
                if(fa[i][x]&&seg::query(rt[st[fa[i][x]]-1],rt[ed[fa[i][x]]],1,n,L,R)==0)     
                    x=fa[i][x];       
            }               
            int point=fa[0][x];      
            // 关键节点       
            int lca=query(1,n,1,L,R).key;   
            int ans=dis[p]-dis[point]+(dep[lca]>=dep[point]?dis[lca]-dis[point]:0);      
            return ans;   
        }                      
    }
    int main() 
    { 
        // setIO("input");  
        int i,j,Q;      
        scanf("%d%d",&n,&Q);  
        for(i=1;i<n;++i) 
        {
            int x,y,c;    
            scanf("%d%d%d",&x,&y,&c),add(x,y,c),add(y,x,c);      
        }
        dfs(1,0);                             
        build(1,n,1); 
        seg::build(rt[0],1,n);      
        for(i=1;i<=n;++i) rt[i]=seg::update(rt[i-1],1,n,ge[i],1);                  
        int lastans=0;        
        while(Q--) 
        {
            int p,l,r; 
            scanf("%d%d%d",&p,&l,&r);     
            p^=lastans,l^=lastans,r^=lastans;   
            lastans=calc(p,l,r);       
            printf("%d
    ",lastans);   
        }
        return 0;
    }
    

      

  • 相关阅读:
    写了一个随机图片API接口,用来做博客园随机背景,欢迎使用,禁止爬取,需要套图可以直接联系博主
    CentOS7.5 部署Flask项目, 并且安装selenium和Chrome、 Chromedriver、tesseract和MongoDB,执行服务和脚本
    重新写了一个东南大学体育场馆的定时预约脚本,使用selenium和chromedriver实现,tesseract识别验证码
    Python基础到进阶之02 文件读写和JSON格式
    Python基础到进阶之01类函数、实例函数和静态函数
    nmap终极使用手册(超详细)
    基于serverless+hexo三分钟部署博客
    【转】Serverless 的运行原理与组件架构
    【转】Serverless 基本概念入门
    什么是服务端渲染,为什么要使用服务端渲染
  • 原文地址:https://www.cnblogs.com/guangheli/p/12303813.html
Copyright © 2011-2022 走看看