解题:LNOI 2014 LCA
这题有点意思
转化问题,我们把询问区间的点到根链加,再查询询问点到根的权值和就是每个询问的答案。
然后如果你数据结构没学傻只需要差分一下就可以扫一遍出解了
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#define vpii vector<pair<int,int> >
#define vpit vector<pair<int,int> >::iterator
using namespace std;
const int N=,M=,mod=;
int p[N],noww[M],goal[M],val[M],laz[M],siz[N];
int far[N],dep[N],imp[N],dfn[N],top[N],ans[N];
int n,q,t1,t2,t3,cnt,tot; vpii lp[N],rp[N];
void Add(int &x,int y)
{
x+=y;
if(x>=mod) x-=mod;
}
void Link(int f,int t)
{//printf("Link %d with %d",f,t);
noww[++cnt]=p[f];
goal[cnt]=t,p[f]=cnt;
noww[++cnt]=p[t];
goal[cnt]=f,p[t]=cnt;
}
void Release(int nde,int l,int r)
{
if(laz[nde])
{
int mid=(l+r)/,ls=*nde,rs=*nde+,&lz=laz[nde];
val[ls]+=lz*(mid-l+),laz[ls]+=lz;
val[rs]+=lz*(r-mid),laz[rs]+=lz,lz=;
}
}
void Change(int nde,int l,int r,int ll,int rr,int tsk)
{
if(l>rr||r<ll)
return ;
else if(l>=ll&&r<=rr)
val[nde]+=tsk*(r-l+),laz[nde]+=tsk;
else
{
int mid=(l+r)/,ls=*nde,rs=*nde+; Release(nde,l,r);
Change(ls,l,mid,ll,rr,tsk),Change(rs,mid+,r,ll,rr,tsk);
val[nde]=val[ls]+val[rs];
}
}
int Query(int nde,int l,int r,int ll,int rr)
{
if(l>rr||r<ll)
return ;
else if(l>=ll&&r<=rr)
return val[nde];
else
{
int mid=(l+r)/,ls=*nde,rs=*nde+; Release(nde,l,r);
return Query(ls,l,mid,ll,rr)+Query(rs,mid+,r,ll,rr);
}
}
void DFS(int nde,int fth,int dth)
{
int tmp=;
siz[nde]=,far[nde]=fth,dep[nde]=dth;
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth)
{
DFS(goal[i],nde,dth+);
siz[nde]+=siz[goal[i]];
if(siz[goal[i]]>tmp)
tmp=siz[goal[i]],imp[nde]=goal[i];
}
}
void Decompose(int nde,int tpp)
{
dfn[nde]=++tot,top[nde]=tpp;
if(imp[nde])
{
Decompose(imp[nde],tpp);
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=imp[nde]&&goal[i]!=far[nde])
Decompose(goal[i],goal[i]);
}
}
void Chain_Change(int x,int y,int v)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
Change(,,n,dfn[top[x]],dfn[x],v),x=far[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
Change(,,n,dfn[x],dfn[y],v);
}
int Chain_Query(int x,int y)
{
int ret=;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ret+=Query(,,n,dfn[top[x]],dfn[x]),x=far[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
ret+=Query(,,n,dfn[x],dfn[y]); return ret;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)
scanf("%d",&t1),Link(t1+,i);
for(int i=;i<=q;i++)
{
scanf("%d%d%d",&t1,&t2,&t3);
lp[t1].push_back(make_pair(i,t3+));
rp[t2+].push_back(make_pair(i,t3+));
}
DFS(,,),Decompose(,);
for(int i=;i<=n;i++)
{
Chain_Change(,i,);
for(vpit it=lp[i].begin();it!=lp[i].end();it++)
ans[it->first]-=Chain_Query(,it->second);//,printf("%d-=%d\n",it->first,Chain_Query(1,it->second));
for(vpit it=rp[i].begin();it!=rp[i].end();it++)
ans[it->first]+=Chain_Query(,it->second);//,printf("%d+=%d\n",it->first,Chain_Query(1,it->second));
}
for(int i=;i<=q;i++)
printf("%d\n",ans[i]%mod);
return ;
}
解题:LNOI 2014 LCA的更多相关文章
- [LNOI 2014]LCA
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先. ...
- 【LNOI 2014】 LCA
[题目链接] 点击打开链接 [算法] 考虑求lca(x,y)的深度 我们可以将从根到x路径上的点都打上标记,然后,询问y到根上路径的权值和 那么,求sigma(depth(lca(i,z)))(l & ...
- [Codevs1519]过路费解题报告|最小生成树|LCA
在某个遥远的国家里,有 n个城市.编号为 1,2,3,…,n.这个国家的政府修建了m 条双向道路,每条道路连接着两个城市.政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值. ...
- bzoj 4012: [HNOI2015]开店
Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现 ...
- [GXOI/GZOI2019]旧词
很像LNOI 2014 LCA那道题. 同样的套路,离线以后直接扫描线. k=1的话就是原题. 考虑一般情况. 原本的做法是对x到根的这条链做一下区间+1操作,目的是为了是的在深度为i的位置得到的贡献 ...
- POJ 1470 Closest Common Ancestors (模板题)(Tarjan离线)【LCA】
<题目链接> 题目大意:给你一棵树,然后进行q次询问,然后要你统计这q次询问中指定的两个节点最近公共祖先出现的次数. 解题分析:LCA模板题,下面用的是离线Tarjan来解决.并且为了代码 ...
- POJ 1330 Nearest Common Ancestors (模板题)【LCA】
<题目链接> 题目大意: 给出一棵树,问任意两个点的最近公共祖先的编号. 解题分析:LCA模板题,下面用的是树上倍增求解. #include <iostream> #inclu ...
- 交通运输线(LCA)
题目大意: 战后有很多城市被严重破坏,我们需要重建城市.然而,有些建设材料只能在某些地方产生.因此,我们必须通过城市交通,来运送这些材料的城市.由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市 ...
- [hdu3078]Network(LCA+排序)
题意:维护树上两点之间的最短路径,其一,将点a的值变为b,其二,求路径上第k大的值. 解题关键:LCA+sort 复杂度:$O(qn\log n + n\log n)$ 数据弱不怪我 //#pragm ...
随机推荐
- Android Device Monitor 文件管理的常见问题 - z
Android Device Monitor 是 Android Studio 中用于监测模拟器或真机运行状态的一款开发者工具.但开发者在使用它的过程中往往会遇到很多问题,尤其对于新手.本文分析了实际 ...
- 大数据入门第十六天——流式计算之storm详解(二)常用命令与wc实例
一.常用命令 1.提交命令 提交任务命令格式:storm jar [jar路径] [拓扑包名.拓扑类名] [拓扑名称] torm jar examples/storm-starter/storm-st ...
- 20155210 Exp7 网络欺诈防范
Exp7 网络欺诈防范 SET工具建立冒名网站 首先利用lsof -i:80或者netstat -tupln |grep 80查询80端口的使用情况(我的电脑80端口没有被占用,如果被占用,则用kil ...
- 【php增删改查实例】第五节 - easyUI的基本使用
1. 列表组件 datagrid 1.1 创建一个grid.html <html> <head> <meta charset="utf-8" /> ...
- SSIS 你真的了解事务吗?
事务用于处理数据的一致性,事务的定义是,处于同一个事务中的操作是一个工作单元,要么全部执行成功,要么全部执行失败.把事务的概念应用到在实际的SSIS Package场景中,如何在Package中实现事 ...
- JavaWeb项目学习教程(1) 准备阶段
写在最前面 为什么要写一个这样的教程?作为一个软件工程专业的学生,上课老师讲得飞快,几乎都是在课后自己消化,我知道学习记录的重要性.我自己本身还有很多很多基础的东西都没有学会,比较博客园的人有很大的差 ...
- Linux使用expect实现免手动密码输入,linux免密码登陆
使用expect实现自动登录的脚本,网上有很多,可是都没有一个明白的说明,初学者一般都是照抄.收藏.可是为什么要这么写却不知其然.本文用一个最短的例子说明脚本的原理. 脚本代码如下: ###### ...
- Unity2D 面向目标方向
在2d空间上,假设角色的自身的y轴方向为正方向,如果要让角色随时面向一个目标点. 这里假设(0,0)点为目标点 第一种: Vector3 v = Vector3.zero - transform.po ...
- 使用kubeadm安装kubernetes高可用集群
kubeadm安装kubernetes高可用集群搭建 第一步:首先搭建etcd集群 yum install -y etcd 配置文件 /etc/etcd/etcd.confETCD_NAME=inf ...
- Codeforces Round #546 (Div. 2) E - Nastya Hasn't Written a Legend
这题是一个贼搞人的线段树 线段树维护的是 区间和a[i - j] 首先对于update的位置可以二分查找 其次update时候的lazy比较技巧 比如更新的是 l-r段,增加的是c 那么这段的值为: ...