zoukankan      html  css  js  c++  java
  • 【BZOJ 3626】 [LNOI2014]LCA【在线+主席树+树剖】

    题目链接:

      TP

    题解:

        可能是我比较纱布,看不懂题解,只好自己想了……

      先附一个离线版本题解[Ivan]

      我们考虑对于询问区间是可以差分的,然而这并没有什么卵用,然后考虑怎么统计答案。

      首先LCA一定是z的祖先(这里说的祖先包括自己,以下祖先均为此概念)节点,也就是是说我们只要计算出每个祖先节点的贡献就可以了,再考虑每个祖先的贡献如何计算。

      我们发现对于深度其实是该点到root的路径点数,所以我们可以这样想,我们询问z的祖先的答案,就是在计算有对于给定区间有多少个点经过了z的祖先。

      那么思路到这里就很清晰了,我们先把每个点到root的路径上的点权都加1,在询问的时候用历史版本做差分即可,那么带永久化标记的主席树+树剖啊QwQ。

      至于时间复杂度,有理有据的$O(nlog^2)$。

    代码:

      

      1 #define Troy 
      2 
      3 #include <bits/stdc++.h>
      4 
      5 using namespace std;
      6 
      7 inline int read(){
      8     int s=0,k=1;char ch=getchar();
      9     while(ch<'0'|ch>'9')    ch=='-'?k=-1:0,ch=getchar();
     10     while(ch>47&ch<='9')    s=s*10+(ch^48),ch=getchar();
     11     return s*k;
     12 }
     13 
     14 const int N=5e4+5,mod=201314;
     15 
     16 int n,Q;
     17 
     18 struct edges{
     19     int v;edges *last;
     20 }edge[N<<1],*head[N];int cnt;
     21 
     22 inline void push(int u,int v){
     23     edge[++cnt]=(edges){v,head[u]};head[u]=edge+cnt;
     24 }
     25 
     26 class Persistent_Segment_tree{
     27 public:
     28     inline void add(int pos,int l,int r){
     29         add(root[pos-1],root[pos],1,n,l,r);
     30     }
     31     inline int query(int last,int pos,int l,int r){
     32         return query(root[last-1],root[pos],1,n,l,r,0);
     33     }
     34     inline void build(){
     35         root[0]=tree;
     36         root[0]->lc=tree;
     37         root[0]->rc=tree;
     38         cnt_tree=1;
     39     }
     40     inline int  out(){
     41         return cnt_tree;
     42     }
     43 private:
     44     struct Tree{
     45         Tree *lc,*rc;
     46         int sign_per,val;
     47         Tree(){sign_per=val=0;lc=rc=NULL;}
     48     }tree[N<<7],*root[N<<5];int cnt_tree;
     49     inline void add(Tree *p,Tree *&u,int l,int r,int x,int y){
     50         u=tree+cnt_tree;cnt_tree++;
     51         *u=*p;
     52         u->val+=y-x+1;
     53         u->val%=mod;
     54         if(x<=l&&r<=y){;u->sign_per++;return;}
     55         int mid=l+r>>1;
     56         if(x>mid)   add(p->rc,u->rc,mid+1,r,x,y);
     57         else    if(y<=mid)  add(p->lc,u->lc,l,mid,x,y);
     58         else    add(p->lc,u->lc,l,mid,x,mid),add(p->rc,u->rc,mid+1,r,mid+1,y);
     59     }
     60     inline int query(Tree *p,Tree *u,int l,int r,int x,int y,int sign_p){
     61         if(x<=l&&r<=y){
     62             return (sign_p*1ll*(r-l+1)%mod+u->val-p->val)%201314+mod;
     63         }
     64         int mid=l+r>>1,ret=0;
     65         if(y>mid)   ret+=query(p->rc,u->rc,mid+1,r,x,y,sign_p+u->sign_per-p->sign_per);
     66         if(x<=mid)  ret+=query(p->lc,u->lc,l,mid,x, y, sign_p+u->sign_per-p->sign_per);
     67         return ret%201314;
     68     }
     69 }war;
     70 
     71 int fa[N],g[N],size[N],heavy[N],tid[N],idx,deep[N],L[N],R[N];
     72 
     73 inline void dfs(int x){
     74     size[x]=1;
     75     for(edges *i=head[x];i;i=i->last)   if(i->v!=fa[x]){
     76         deep[i->v]=deep[x]+1,fa[i->v]=x,dfs(i->v);
     77         size[x]+=size[i->v];
     78         if(size[heavy[x]]<size[i->v])
     79             heavy[x]=i->v;
     80     }
     81 }
     82 
     83 inline void dfs(int x,int grand){
     84     tid[x]=++idx;
     85     g[x]=grand;
     86     if(heavy[x]){
     87         dfs(heavy[x],grand);
     88         for(edges *i=head[x];i;i=i->last)   if(i->v!=fa[x]&&i->v!=heavy[x]){
     89             dfs(i->v,i->v);
     90         }
     91     }
     92 }
     93 
     94 inline void add(int x){
     95     L[x]=idx+1;
     96     int t=x;
     97     while(g[x]!=1){
     98         ++idx;
     99         war.add(idx,tid[g[x]],tid[x]);
    100         x=fa[g[x]];
    101     }
    102     ++idx,war.add(idx,tid[1],tid[x]);
    103     R[t]=idx;
    104 }
    105 
    106 inline int query(int x,int l,int r){
    107     int ret=0;
    108     while(g[x]!=1){
    109         (ret+=war.query(L[l],R[r],tid[g[x]],tid[x]))%=mod;
    110         x=fa[g[x]];
    111     }        
    112     ret+=war.query(L[l],R[r],tid[1],tid[x]);
    113     return ret%mod;
    114 }
    115 
    116 int main(){
    117     n=read(),Q=read();
    118     for(int i=2;i<=n;++i){
    119         int x=read()+1;
    120         push(x,i),push(i,x);
    121     }
    122     dfs(1);dfs(1,1);idx=0;
    123     war.build();
    124     for(int i=1;i<=n;++i){
    125         add(i);
    126     }
    127     while(Q--){
    128         int l=read()+1,r=read()+1,z=read()+1;
    129         printf("%d
    ",(query(z,l,r)%mod+mod)%mod);
    130     }
    131 }
  • 相关阅读:
    jQuery的动画以及扩展功能
    yii2 redirect重定向
    nvaicat mysql ssh 跳板机(堡垒机???)连接服务器
    Linux下Redis的安装
    深入理解PHP的运行模式
    thinkphp5 如何监听sql?
    thinkphp5 如何使用查询事件?
    layui laydate is not defined
    CSS 实现图片灰度效果 兼容各种浏览器
    PHP基础学习----函数
  • 原文地址:https://www.cnblogs.com/Troywar/p/7777959.html
Copyright © 2011-2022 走看看