题目描述:

网址:http://www.lydsy.com/JudgeOnline/problem.php?id=3626
大意:
给出一个n个节点的有根树(编号为0到n-1,根节点为0)。
一个点的深度定义为这个节点到根的距离+1。
设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。
有q次询问,每次询问给出l r z,求\(∑dep[LCA(i,z)],{l<=i<=r}\)。
---(即,求在[l,r]区间内的每个节点i与z的最近公共祖先的深度之和)

题目解法:

考虑求\(LCA(i,z)\),z是不变的。
那么如果把 \(i到root的路径\) 权值加1,最后答案就为 \(z到root路径\) 上的权值和。
这是一个常见的套路啦。
因为这个我们可以对每一次的询问进行差分。
查询答案变为\(Ans = Query(R) - Query(L-1);\)
这样就可以离线做:
我们从左往右依次增加 1~N到root的路径权值 ,然后 查询对应相关询问中 z到root路径 的权值和即可。
所有东西都直接用LCT维护即可。

实现代码

#include<bits/stdc++.h>
#define ll long long
#define RG register
#define IL inline
#define maxn 60000
#define mod 201314
using namespace std;

IL ll gi(){
    RG ll date = 0, m = 1;  RG char ch = 0;
    while(ch!='-'&&(ch<'0'||ch>'9'))ch = getchar();
    if(ch == '-'){m = -1; ch = getchar();}
    while(ch>='0' && ch<='9')
       {date=date*10+ch-'0'; ch = getchar();}
    return date*m;
}

ll N,Q,root; struct Question {ll L,R,Z;}qs[maxn];
ll ch[maxn][2],fa[maxn],rev[maxn],sum[maxn],sz[maxn],laz[maxn],val[maxn];
vector<ll>gpL[maxn],gpR[maxn]; ll stk[maxn]; 

IL bool Son(RG ll x){return ch[fa[x]][1] == x;}
IL bool Isroot(RG ll x){return (ch[fa[x]][1] != x && ch[fa[x]][0] != x);}
IL bool Reverse(RG ll x){swap(ch[x][0],ch[x][1]); rev[x]^=1;}
IL void PushUp(RG ll x){
    sum[x] = ( val[x] + sum[ch[x][0]] + sum[ch[x][1]] )%mod;
    sz[x] = 1 + sz[ch[x][0]] + sz[ch[x][1]];
}
IL void PushDown(RG ll x){
    RG ll ls = ch[x][0],rs = ch[x][1];
    if(laz[x]){
        sum[ls] = (sum[ls] + 1ll*laz[x]*sz[ls])%mod;
        sum[rs] = (sum[rs] + 1ll*laz[x]*sz[rs])%mod;
        val[ls] = (val[ls] + laz[x])%mod;
        val[rs] = (val[rs] + laz[x])%mod;
        laz[ls] = (laz[x] + laz[ls])%mod;
        laz[rs] = (laz[x] + laz[rs])%mod;
        laz[x] = 0;
    }
    if(rev[x]){ Reverse(ls); Reverse(rs);rev[x] ^= 1; }
}

IL void Rot(RG ll x){
    RG ll y = fa[x],z = fa[y],c = Son(x);
    if(!Isroot(y))ch[z][Son(y)] = x; fa[x] = z;
    ch[y][c] = ch[x][!c]; fa[ch[y][c]] = y;
    ch[x][!c] = y; fa[y] = x; PushUp(y);
}
IL void Splay(RG ll x){
    stk[++stk[0]] = x;
    for(RG ll y = x; !Isroot(y); y = fa[y])stk[++stk[0]] = fa[y];
    while(stk[0])PushDown(stk[stk[0]--]);
    for(RG ll y = fa[x]; !Isroot(x); Rot(x),y = fa[x])
        if(!Isroot(y))Son(x) ^ Son(y) ? Rot(x) : Rot(y);
    PushUp(x);
}

IL void Access(RG ll x){ for(RG ll y = 0; x; y = x,x = fa[x])Splay(x),ch[x][1] = y,PushUp(x); }
IL void Makeroot(RG ll x){ Access(x); Splay(x); Reverse(x); }
IL void Split(RG ll x,RG ll y){ Makeroot(x); Access(y); Splay(y); }
IL void Link(RG ll x,RG ll y){ Makeroot(x); fa[x] = y; }

//已经把所有点的标号都加了1。
int main(){
    N = gi(); Q = gi();
    for(RG ll i = 1; i <= N; i ++)sz[i] = 1;
    for(RG ll i = 2; i <= N ; i ++)Link(gi()+1,i);
    for(RG ll i = 1; i <= Q ; i ++){
        qs[i].L = (gi()-1)+1; qs[i].R = gi()+1; qs[i].Z = gi()+1;
        gpL[qs[i].L].push_back(i);
        gpR[qs[i].R].push_back(i);
    }
    root = 1;
    for(RG ll i = 1; i <= N; i ++){
        Split(root,i);
        val[i]++; laz[i]++;
        sum[i] = sum[i] + sz[i];
        for(RG ll j = 0,c; j < gpL[i].size(); j ++)
            c = gpL[i][j] ,Split(root,qs[c].Z) , qs[c].L = sum[qs[c].Z];
        for(RG ll j = 0,c; j < gpR[i].size(); j ++)
            c = gpR[i][j] ,Split(root,qs[c].Z) , qs[c].R = sum[qs[c].Z];
    }
    for(RG ll i = 1; i <= Q; i ++)
        printf("%lld\n",(qs[i].R - qs[i].L + mod)%mod);
    return 0;
}

[LNOI2014] LCA的更多相关文章

  1. BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2050  Solved: 817[Submit][Status ...

  2. bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1272  Solved: 451[Submit][Status ...

  3. bzoj 3626: [LNOI2014]LCA 离线+树链剖分

    3626: [LNOI2014]LCA Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 426  Solved: 124[Submit][Status] ...

  4. BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )

    说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...

  5. 洛谷 P4211 [LNOI2014]LCA 解题报告

    [LNOI2014]LCA 题意 给一个\(n(\le 50000)\)节点的有根树,询问\(l,r,z\),求\(\sum_{l\le i\le r}dep[lca(i,z)]\) 一直想启发式合并 ...

  6. P4211 [LNOI2014]LCA

    P4211 [LNOI2014]LCA 链接 分析: 首先一种比较有趣的转化是,将所有点到1的路径上都+1,然后z到1的路径上的和,就是所有答案的deep的和. 对于多次询问,要么考虑有把询问离线,省 ...

  7. 【BZOJ3626】[LNOI2014]LCA 离线+树链剖分+线段树

    [BZOJ3626][LNOI2014]LCA Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度 ...

  8. P4211 [LNOI2014]LCA LCT

    P4211 [LNOI2014]LCA 链接 loj luogu 思路 多次询问\(\sum\limits_{l \leq i \leq r}dep[LCA(i,z)]\) 可以转化成l到r上的点到根 ...

  9. [BZOJ3626] [LNOI2014]LCA(树链剖分)

    [BZOJ3626] [LNOI2014]LCA(树链剖分) 题面 给出一棵N个点的树,要求支持Q次询问,每次询问一个点z与编号为区间[l,r]内的点分别求最近公共祖先得到的最近公共祖先深度和.N, ...

  10. [bzoj3626][LNOI2014]LCA

    Description 给出一个$n$个节点的有根树(编号为$0$到$n-1$,根节点为$0$). 一个点的深度定义为这个节点到根的距离$+1$. 设$dep[i]$表示点$i$的深度,$lca(i, ...

随机推荐

  1. Redis 学习(三) —— 事务、消息发布订阅

    一.Redis事务 Redis 提供的事务机制与传统的数据库事务有些不同,传统数据库事务必须维护以下特性:原子性(Atomicity), 一致性(Consistency),隔离性(Isolation) ...

  2. 企业级docker仓库Harbor部署

    1.安装环境下载离线安装包地址https://github.com/vmware/harbor/releases/yum install -y dockerpip install -i https:/ ...

  3. 升级gitlab

    https://gitlab.com/gitlab-org/gitlab-ce/tree/master/doc/update https://about.gitlab.com/update/#cent ...

  4. Go生成easyjson文件

    [生成easyjson文件] cd services/api_adapter/aliafp   #先删除已有的aliafp_easyjson.go文件,并且把除了aliafp.go以外的其他文件移动到 ...

  5. Centos7新功能

    Centos7 单用户模式   centos7里不再有0-6启动级别,而是4个target   graphical.target  多人模式,支持图形和命令行两种登录,对应之前的3,5级别   mul ...

  6. angular2-qrcode (转)

    插件选择 angular2-qrcode npm install angular2-qrcode --savecnpm install angular2-qrcode --save 参考github ...

  7. According to TLD or attribute directive in tag file, attribute value does not accept any expressions报错解决办法

    1.出现原因: 导入的uri由于不是正确的导致这个jstl不支持el的表达式 jstl uri导入错误:   <%@ taglib prefix="c" uri=" ...

  8. SpringBoot 中常用注解

    本篇博文将介绍几种SpringBoot 中常用注解 其中,各注解的作用为: @PathVaribale 获取url中的数据 @RequestParam 获取请求参数的值 @GetMapping 组合注 ...

  9. Git (gnome-ssh-askpass:3871): Gtk-WARNING **: cannot open display:

    在使用Git在客户端使用git push 命令提交文件到github时,出现报错 (gnome-ssh-askpass:): Gtk-WARNING **: cannot open display: ...

  10. C# 13行代码带你模拟登录QQ空间

    最近想做一个QQ空间点赞的小工具,于是晚上下班回来就开始分析PC版的QQ空间,打开Chrome,切换到Network,然后输入账号密码,然后点击登录... 然后,我曹....一堆请求就开始了....搞 ...