P4211[BZOJ 3626] [LNOI2014]LCA
题目描述
给出一个n个节点的有根树(编号为0到n-1,根节点为0)。一个点的深度定义为这个节点到根的距离+1。 设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先。 有q次询问,每次询问给出l r z,求 ∑l<=i<=r dep[LCA(i,z)]
输入输出格式
输入格式:
第一行2个整数n q。 接下来n-1行,分别表示点1到点n-1的父节点编号。 接下来q行,每行3个整数l r z。
输出格式:
输出q行,每行表示一个询问的答案。每个答案对201314取模输出
输入输出样例
说明
共5组数据,n与q的规模分别为10000,20000,30000,40000,50000。
题解
话说这题题解基本都是抄清华爷gconeice的吧……实在不会啊……
暴力的想法是,每次把要询问的点向上打上标记,然后让z点向上走,第一个遇到有标记的点就是lca
又因为lca的祖先也有标记,我们可以发现它的深度就是它祖先的标记总数
那么我们可以把每个点到根的路径都+1,然后询问z到根的和,就是答案了
很明显可以用树剖或LCT解决(然而本蒟蒻写不来LCT……)
多组询问如何解决?
我们可以把区间[l,r]的答案拆成[1,r]-[1,l-1]
然后把询问按端点排序,依次向后推,就可以满足条件了……
ps:hzwer大佬强无敌……代码看了我好久才弄明白怎么回事orz
//minamoto
#include<bits/stdc++.h>
#define N 50005
#define mod 201314
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<15,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
typedef long long ll;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
int n,m,num,tot;
int sz[N],fa[N],son[N],cnt[N],rk[N],dep[N],top[N];
int ver[N],Next[N],head[N];
int sum[N<<],tag[N<<],l[N<<],r[N<<];
struct que{int z,ans1,ans2;}q[N];
struct data{int num,p;bool flag;}a[N<<];
bool operator <(data a,data b){return a.p<b.p;}
void add(int u,int v){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot;
}
void dfs1(int u){
sz[u]=;dep[u]=dep[fa[u]]+;
for(int i=head[u];i;i=Next[i]){
if(ver[i]==fa[u]) continue;
int v=ver[i];
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u){
if(top[u]==-) top[u]=u;
cnt[u]=++num,rk[num]=u;
if(son[u]) top[son[u]]=top[u],dfs2(son[u]);
for(int i=head[u];i;i=Next[i]){
int v=ver[i];
if(v!=fa[u]&&v!=son[u]) dfs2(v);
}
}
void pushdown(int p){
if(tag[p]){
int lc=p<<,rc=p<<|;
sum[lc]+=tag[p]*(r[lc]-l[lc]+);
sum[rc]+=tag[p]*(r[rc]-l[rc]+);
tag[lc]+=tag[p];
tag[rc]+=tag[p];
tag[p]=;
}
}
void build(int p,int ll,int rr){
l[p]=ll,r[p]=rr;
if(ll==rr) return;
int mid=(ll+rr)>>;
build(p<<,ll,mid);
build(p<<|,mid+,rr);
}
void update(int p,int ll,int rr)
{
if(ll<=l[p]&&rr>=r[p])
{
sum[p]+=r[p]-l[p]+;
++tag[p];
return;
}
pushdown(p);
int mid=(l[p]+r[p])>>;
if(ll<=mid) update(p<<,ll,rr);
if(rr>mid) update((p<<)+,ll,rr);
sum[p]=sum[p<<]+sum[p<<|];
}
void solve_update(int x,int f){
while(top[x]!=top[f]){
update(,cnt[top[x]],cnt[x]);
x=fa[top[x]];
}
update(,cnt[f],cnt[x]);
}
int query(int p,int ll,int rr)
{
if(ll<=l[p]&&rr>=r[p]) return sum[p];
pushdown(p);
int mid=(l[p]+r[p])>>;
int val=;
if(ll<=mid) val+=query(p<<,ll,rr);
if(rr>mid) val+=query((p<<)+,ll,rr);
return val;
}
int solve_query(int x,int f){
int sum=;
while(top[x]!=top[f]){
sum+=query(,cnt[top[x]],cnt[x]);
sum%=mod;
x=fa[top[x]];
}
sum+=query(,cnt[f],cnt[x]);sum%=mod;
return sum;
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),m=read();
memset(top,-,sizeof(top));
for(int i=;i<n;++i){
int x=read();add(x,i);
}
int tot=;
for(int i=;i<=m;++i){
int l=read(),r=read();
q[i].z=read();
a[++tot].p=l-,a[tot].num=i,a[tot].flag=;
a[++tot].p=r,a[tot].num=i,a[tot].flag=;
}
build(,,n);
sort(a+,a++tot);
dfs1(),dfs2();
int now=-;
for(int i=;i<=tot;++i){
while(now<a[i].p){
++now;
solve_update(now,);
}
int t=a[i].num;
if(!a[i].flag) q[t].ans1=solve_query(q[t].z,);
else q[t].ans2=solve_query(q[t].z,);
}
for(int i=;i<=m;++i)
printf("%d\n",(q[i].ans2-q[i].ans1+mod)%mod);
return ;
}
P4211[BZOJ 3626] [LNOI2014]LCA的更多相关文章
- BZOJ 3626: [LNOI2014]LCA [树链剖分 离线|主席树]
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2050 Solved: 817[Submit][Status ...
- bzoj 3626 [LNOI2014]LCA(离线处理+树链剖分,线段树)
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1272 Solved: 451[Submit][Status ...
- bzoj 3626: [LNOI2014]LCA 离线+树链剖分
3626: [LNOI2014]LCA Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 426 Solved: 124[Submit][Status] ...
- BZOJ 3626: [LNOI2014]LCA( 树链剖分 + 离线 )
说多了都是泪啊...调了这么久.. 离线可以搞 , 树链剖分就OK了... -------------------------------------------------------------- ...
- [BZOJ 3626] [LNOI2014] LCA 【树链剖分 + 离线 + 差分询问】
题目链接: BZOJ - 3626 题目分析 考虑这样的等价问题,如果我们把一个点 x 到 Root 的路径上每个点的权值赋为 1 ,其余点的权值为 0,那么从 LCA(x, y) 的 Depth 就 ...
- BZOJ 3626 [LNOI2014]LCA:树剖 + 差分 + 离线【将深度转化成点权之和】
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3626 题意: 给出一个n个节点的有根树(编号为0到n-1,根节点为0,n <= 50 ...
- BZOJ 3626 [LNOI2014]LCA 树剖+(离线+线段树 // 在线+主席树)
BZOJ 4012 [HNOI2015]开店 的弱化版,离线了,而且没有边权(长度). 两种做法 1 树剖+离线+线段树 这道题求的是一个点zzz与[l,r][l,r][l,r]内所有点的lcalca ...
- bzoj 3626: [LNOI2014]LCA
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...
- bzoj 3626 : [LNOI2014]LCA (树链剖分+线段树)
Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q ...
随机推荐
- eclipse cut copy paste plugin
The Cut Copy Paste Plus plug-in enhances the standard Cut, Copy and Paste commands in Eclipse IDE. W ...
- 快速变幻AABB的顶点
[快速变幻AABB的顶点] 当要变幻一个AABB时,可以快速计算变幻后顶点的AABB.当有旋转时,根据8个顶点变幻后的AABB可能会更大. AABB的八个顶点需分别作如下变幻: 注意到为了使 x' 最 ...
- 41. First Missing Positive (HashTable)
Given an unsorted integer array, find the first missing positive integer. For example,Given [1,2,0] ...
- PLSQL优化基础和性能优化 (学习总结)
PLSQL优化基础和性能优化 (学习总结) 网上有一篇关于PLSQL优化的文章,不错,个人根据自己的经验再稍加整理和归纳,总结PLSQL优化和性能调优 适合有一定PLSQL基础,需要进一步提高的学友看 ...
- gradle 构建测试
以后决不能再犯此类低级错误
- golang apns升级到http2
记录一下golang中升级apns,使用http2替换http1.1的详细过程. apns使用http2的好处就不用再说了,网上一搜一堆信息.苹果的apns推送在2015年8月就支持了http2协议, ...
- advance shading--光源的类型
我们这里讨论的光源类型都有一个相同点,就是,我们考量的都是光源上的一个点,对于物体表面上一个点的影响,也就是说立体角趋近为零的情况. 这里光源分为两类,一类是方向光,假设光源在无限远处.另一类是点光源 ...
- Zookeeper 源码(二)序列化组件 Jute
Zookeeper 源码(二)序列化组件 Jute 一.序列化组件 Jute 对于一个网络通信,首先需要解决的就是对数据的序列化和反序列化处理,在 ZooKeeper 中,使用了Jute 这一序列化组 ...
- centos 安装部署.net core站点
安装 net core sudo rpm -Uvh https://packages.microsoft.com/config/rhel/7/packages-microsoft-prod.rpm s ...
- HBase 强制删除表
业务系统中有一张表drop不掉了. 可以disable,就是drop不掉. 解决办法: 1.将HDFS上的数据删除或移动 hadoop fs -mv /hbase/<table_name> ...