• Bzoj3626 [LNOI2014]LCA


     

    Time Limit: 10 Sec  Memory Limit: 128 MB

    Submit: 2007  Solved: 800

    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。

    Source

    树链剖分+差分

    如果只有一个询问区间的话,可以暴力处理[L,R]区间内的每一个点,将结点到根的路径上的每个点权值+1,之后统计z到根结点路径上的点权和,就是答案。

    ↑可以用树链剖分来维护,做到O(nlog(n))复杂度。

    对于多个询问区间,可以O(n)扫描1到n的每个结点,如上添加权值,若某个点是询问区间起点,记录该询问的“初始状态”ans1,若某个点是询问区间终点,记录该询问的“终状态”ans2,ans2-ans1就是该询问的答案。

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<cmath>
      6 #include<vector>
      7 #define lc rt<<1
      8 #define rc rt<<1|1
      9 using namespace std;
     10 const int mod=201314;
     11 const int mxn=50010;
     12 int read(){
     13     int x=0,f=1;char ch=getchar();
     14     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     15     while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();}
     16     return x*f;
     17 }
     18 struct edge{int v,nxt;}e[mxn<<1];
     19 int hd[mxn],mct=0;
     20 void add_edge(int u,int v){
     21     e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return;
     22 }
     23 struct node{int fa,son;int top,size;int w,e;}t[mxn];
     24 int dep[mxn],sz=0;
     25 void DFS1(int u,int fa){
     26     dep[u]=dep[fa]+1;
     27     t[u].fa=fa;t[u].size=1;
     28     for(int i=hd[u];i;i=e[i].nxt){
     29         int v=e[i].v;
     30         DFS1(v,u);
     31         t[u].size+=t[v].size;
     32         if(t[v].size>t[t[u].son].size){
     33             t[u].son=v;
     34         }
     35     }
     36     return;
     37 }
     38 void DFS2(int u,int top){
     39     t[u].w=++sz;t[u].top=top;
     40     if(t[u].son){
     41         DFS2(t[u].son,top);
     42         for(int i=hd[u];i;i=e[i].nxt){
     43             int v=e[i].v;
     44             if(v!=t[u].son && v!=t[u].fa){
     45                 DFS2(v,v);
     46             }
     47         }
     48     }
     49     t[u].e=sz;
     50     return;
     51 }
     52 struct sgt{int sum,mk;}st[mxn<<2];
     53 void pushup(int rt){st[rt].sum=(st[lc].sum+st[rc].sum)%mod;return;}
     54 void pushdown(int l,int r,int rt){
     55     if(st[rt].mk){
     56         st[lc].mk+=st[rt].mk;
     57         st[rc].mk+=st[rt].mk;
     58         int mid=(l+r)>>1;
     59         (st[lc].sum+=st[rt].mk*(mid-l+1))%=mod;
     60         (st[rc].sum+=st[rt].mk*(r-mid))%=mod;
     61         st[rt].mk=0;
     62     }
     63     return;
     64 }
     65 void update(int L,int R,int v,int l,int r,int rt){
     66     if(L<=l && r<=R){
     67         st[rt].mk+=v;
     68         (st[rt].sum+=v*(r-l+1))%=mod;
     69         return;
     70     }
     71     if(st[rt].mk)pushdown(l,r,rt);
     72     int mid=(l+r)>>1;
     73     if(L<=mid)update(L,R,v,l,mid,lc);
     74     if(R>mid)update(L,R,v,mid+1,r,rc);
     75     pushup(rt);
     76     return;
     77 }
     78 int qsum(int L,int R,int l,int r,int rt){
     79     if(L<=l && r<=R){return st[rt].sum;}
     80     if(st[rt].mk)pushdown(l,r,rt);
     81     int mid=(l+r)>>1;
     82     int res=0;
     83     if(L<=mid) res+=qsum(L,R,l,mid,lc);
     84     if(R>mid) res+=qsum(L,R,mid+1,r,rc);
     85     return res%mod;
     86 }
     87 void tadd(int x,int y,int v){
     88     while(t[x].top!=t[y].top){
     89         if(dep[t[x].top]<dep[t[y].top])swap(x,y);
     90         update(t[t[x].top].w,t[x].w,v,1,sz,1);
     91         x=t[t[x].top].fa;
     92     }
     93     if(dep[x]>dep[y])swap(x,y);
     94     update(t[x].w,t[y].w,v,1,sz,1);
     95     return;
     96 }
     97 int asksum(int x,int y){
     98     int res=0;
     99     while(t[x].top!=t[y].top){
    100         if(dep[t[x].top]<dep[t[y].top])swap(x,y);
    101         (res+=qsum(t[t[x].top].w,t[x].w,1,sz,1))%=mod;
    102         x=t[t[x].top].fa;
    103     }
    104     if(dep[x]>dep[y])swap(x,y);
    105     res+=qsum(t[x].w,t[y].w,1,sz,1);
    106     return res;
    107 }
    108 struct query{
    109     int x,v,z;int id;
    110 }q[mxn<<1];
    111 int qct=0;
    112 int cmp(const query a,const query b){
    113     if(a.x!=b.x)return a.x<b.x;
    114     return a.id<b.id;
    115 }
    116 int ans[mxn];
    117 int n,Q;
    118 int main()
    119 {
    120     n=read();Q=read();
    121     int i,j;
    122     for(i=2;i<=n;i++){//点编号整体+1 
    123         j=read()+1;
    124         add_edge(j,i);
    125     }
    126     DFS1(1,0);
    127     DFS2(1,1);
    128     int x,y,z;
    129     for(i=1;i<=Q;i++){
    130         x=read()+1;y=read()+1;z=read()+1;
    131         q[++qct].id=i;q[qct].z=z;q[qct].x=x-1;q[qct].v=1;
    132         q[++qct].id=i;q[qct].z=z;q[qct].x=y;q[qct].v=-1;
    133     }
    134     sort(q+1,q+qct+1,cmp);
    135     int hed=1;
    136     for(i=1;i<=qct;i++){
    137         while(hed<=q[i].x){
    138             tadd(hed,1,1);
    139             hed++;
    140         }
    141         if(q[i].v==1)ans[q[i].id]-=asksum(q[i].z,1);
    142         else ans[q[i].id]+=asksum(q[i].z,1);//差分答案 
    143     }
    144     for(i=1;i<=Q;i++)printf("%d
    ",(ans[i]%mod+mod)%mod);
    145     return 0;
    146 }
  • 相关阅读:
    二级菜单jquery
    js二级导航
    append appendChild appendTo区别
    cssText在 IE6/7/8和chrome/Firefox/IE9+的不同
    cssText
    css slice和splice
    js字符串函数之substring() substr()
    js字符串函数之split()join()
    Python面向对象之:三大特性:继承,封装,多态以及类的约束
    Python3 面向对象之:多继承
  • 原文地址:https://www.cnblogs.com/SilverNebula/p/6185385.html
Copyright © 2020-2023  润新知