zoukankan      html  css  js  c++  java
  • bzoj3626 [LNOI2014]LCA

    Description

    给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。
    设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
    有q次询问,每次询问给出l r z,求sigma_{l<=i<=r}dep[LCA(i,z)]。
    (即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

    Input

    第一行2个整数n q。
    接下来n-1行,分别表示点1到点n-1的父节点编号。
    接下来q行,每行3个整数l r z。

    Output

    输出q行,每行表示一个询问的答案。每个答案对201314取模输出

    Sample Input

    5 2
    0
    0
    1
    1
    1 4 3
    1 4 2

    Sample Output

    8
    5

    HINT

    共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。

    正解:树链剖分+主席树。

    话说HNOI是喜欢出原题吗,这就是15年开店的弱化版啊。。看来要多刷去年的各种省选题了。。

    题解见开店。这题就是边权变为1,答案直接查询,然后就没有什么不同了。

      1 //It is made by wfj_2048~
      2 #include <algorithm>
      3 #include <iostream>
      4 #include <complex>
      5 #include <cstring>
      6 #include <cstdlib>
      7 #include <cstdio>
      8 #include <vector>
      9 #include <cmath>
     10 #include <queue>
     11 #include <stack>
     12 #include <map>
     13 #include <set>
     14 #define inf (1<<30)
     15 #define rhl (201314)
     16 #define N (50005)
     17 #define il inline
     18 #define RG register
     19 #define ll long long
     20 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
     21 
     22 using namespace std;
     23 
     24 struct edge{ int nt,to; }g[N];
     25 
     26 ll sum[130*N];
     27 int lazy[130*N],ls[130*N],rs[130*N],rt[N],ssz;
     28 int head[N],top[N],fa[N],son[N],tid[N],dep[N],sz[N],n,q,cnt,num;
     29 
     30 il int gi(){
     31     RG int x=0,q=1; RG char ch=getchar(); while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
     32     if (ch=='-') q=-1,ch=getchar(); while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); return q*x;
     33 }
     34 
     35 il void insert(RG int from,RG int to){ g[++num]=(edge){head[from],to},head[from]=num; return; }
     36 
     37 il void dfs1(RG int x,RG int p){
     38     fa[x]=p,dep[x]=dep[p]+1,sz[x]=1; RG int v;
     39     for (RG int i=head[x];i;i=g[i].nt){
     40     v=g[i].to; if (v==p) continue;
     41     dfs1(v,x); sz[x]+=sz[v];
     42     if (sz[son[x]]<=sz[v]) son[x]=v;
     43     }
     44     return;
     45 }
     46 
     47 il void dfs2(RG int x,RG int p,RG int anc){
     48     top[x]=anc,tid[x]=++cnt;
     49     if (son[x]) dfs2(son[x],x,anc); RG int v;
     50     for (RG int i=head[x];i;i=g[i].nt){
     51     v=g[i].to; if (v==p || v==son[x]) continue;
     52     dfs2(v,x,v);
     53     }
     54     return;
     55 }
     56 
     57 il void update(RG int x,RG int &y,RG int l,RG int r,RG int xl,RG int xr){
     58     y=++ssz; sum[y]=sum[x],lazy[y]=lazy[x],ls[y]=ls[x],rs[y]=rs[x];
     59     if (xl<=l && r<=xr){ (sum[y]+=r-l+1)%=rhl,lazy[y]++; return; }
     60     RG int mid=(l+r)>>1;
     61     if (xr<=mid) update(ls[x],ls[y],l,mid,xl,xr);
     62     else if (xl>mid) update(rs[x],rs[y],mid+1,r,xl,xr);
     63     else update(ls[x],ls[y],l,mid,xl,mid),update(rs[x],rs[y],mid+1,r,mid+1,xr);
     64     sum[y]=(sum[ls[y]]+sum[rs[y]]+(ll)lazy[y]*(ll)(r-l+1))%rhl; return;
     65 }
     66 
     67 il int query(RG int x,RG int y,RG int l,RG int r,RG int xl,RG int xr,RG ll la){
     68     if (xl<=l && r<=xr) return (int)(sum[y]-sum[x]+la*(ll)(r-l+1)+rhl)%rhl;
     69     RG int mid=(l+r)>>1; la+=lazy[y]-lazy[x];
     70     if (xr<=mid) return query(ls[x],ls[y],l,mid,xl,xr,la);
     71     else if (xl>mid) return query(rs[x],rs[y],mid+1,r,xl,xr,la);
     72     else return query(ls[x],ls[y],l,mid,xl,mid,la)+query(rs[x],rs[y],mid+1,r,mid+1,xr,la);
     73 }
     74 
     75 il void change(RG int x){
     76     RG int la=rt[x-1],u=x;
     77     while (u){
     78     update(la,rt[x],1,n,tid[top[u]],tid[u]);
     79     la=rt[x],u=fa[top[u]];
     80     }
     81     return;
     82 }
     83 
     84 il int Query(RG int x,RG int l,RG int r){
     85     RG int res=0;
     86     while (x){
     87     (res+=query(rt[l-1],rt[r],1,n,tid[top[x]],tid[x],0))%=rhl;
     88     x=fa[top[x]];
     89     }
     90     return res;
     91 }
     92 
     93 il void work(){
     94     n=gi(),q=gi(); RG int l,r,z;
     95     for (RG int i=2;i<=n;++i) fa[i]=gi()+1,insert(fa[i],i);
     96     dfs1(1,0),dfs2(1,0,1); for (RG int i=1;i<=n;++i) change(i);
     97     for (RG int i=1;i<=q;++i){
     98     l=gi()+1,r=gi()+1,z=gi()+1;
     99     printf("%d
    ",Query(z,l,r));
    100     }
    101     return;
    102 }
    103 
    104 int main(){
    105     File("lca");
    106     work();
    107     return 0;
    108 }
  • 相关阅读:
    模拟+位运算 HDOJ 5491 The Next
    树状数组+二分||线段树 HDOJ 5493 Queue
    线段树(区间合并) HDOJ 3308 LCIS
    双端队列 HDOJ 3530 Subsequence
    BFS HDOJ 1242 Rescue
    Codeforces Round #321 (Div. 2)
    区间专题
    递推DP HDOJ 5459 Jesus Is Here
    补题列表2
    引用与指针的异同-基础篇
  • 原文地址:https://www.cnblogs.com/wfj2048/p/6483497.html
Copyright © 2011-2022 走看看