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
0
0
1
1
1 4 3
1 4 2
Sample Output
5
解题思路:
蒟蒻QAQ的我一开始以为是树上莫队。
还好吧,这题其实是将Deep重新理解了一下,就是从根到这个点的距离。
我们发现可以在树链上(到1)加一,最后查询到根的权值和。
发现具有区间可减性。
线段树+树剖搞定。
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll spc<<1
#define rrr spc<<1|1
typedef long long lnt;
const lnt mod=;
using std::sort;
struct trnt{
lnt lzt;
lnt val;
}tr[];
struct pnt{
int hd;
int fa;
int tp;
int dp;
int no;
int wgt;
int ind;
int mxs;
}p[];
struct ent{
int twd;
int lst;
}e[];
int ans[];
struct data{
int no;
bool lft;
int rgt;
int z;
}dt[];
int cnt;
int dfn;
int n,q;
bool cmp(data x,data y)
{
return x.rgt<y.rgt;
}
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void add(int l,int r,int spc,lnt x)
{
if(!spc)
return ;
tr[spc].lzt=(tr[spc].lzt+x)%mod;
tr[spc].val=(tr[spc].val+(((lnt)(r-l+))*x)%mod)%mod;
return ;
}
void pushdown(int spc,int l,int r)
{
if(tr[spc].lzt)
{
int mid=(l+r)>>;
add(l,mid,lll,tr[spc].lzt);
add(mid+,r,rrr,tr[spc].lzt);
tr[spc].lzt=;
}
return ;
}
void pushup(int spc)
{
tr[spc].val=(tr[lll].val+tr[rrr].val)%mod;
}
void update(int l,int r,int ll,int rr,int spc,lnt v)
{
if(ll>r||l>rr)
return ;
if(ll<=l&&r<=rr)
{
add(l,r,spc,v);
return ;
}
pushdown(spc,l,r);
int mid=(l+r)>>;
update(l,mid,ll,rr,lll,v);
update(mid+,r,ll,rr,rrr,v);
pushup(spc);
return ;
}
lnt query(int l,int r,int ll,int rr,int spc)
{
if(ll>r||l>rr)
return 0ll;
if(ll<=l&&r<=rr)
return tr[spc].val;
int mid=(l+r)>>;
pushdown(spc,l,r);
return (query(l,mid,ll,rr,lll)+query(mid+,r,ll,rr,rrr))%mod;
}
void Basic_dfs(int x,int f)
{
p[x].fa=f;
p[x].dp=p[f].dp+;
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(p[to].wgt>maxs)
{
maxs=p[to].wgt;
p[x].mxs=to;
}
}
}
void Build_dfs(int x,int top)
{
if(!x)
return ;
p[x].ind=++dfn;
p[x].tp=top;
Build_dfs(p[x].mxs,top);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].ind)
continue;
Build_dfs(to,to);
}
return ;
}
void Insert(int x)
{
while(p[x].tp!=)
{
update(,n,p[p[x].tp].ind,p[x].ind,,);
x=p[p[x].tp].fa;
}
update(,n,,p[x].ind,,);
return ;
}
lnt Val(int x)
{
lnt ansl=;
while(p[x].tp!=)
{
ansl+=query(,n,p[p[x].tp].ind,p[x].ind,);
ansl%=mod;
x=p[p[x].tp].fa;
}
ansl+=query(,n,,p[x].ind,);
ansl%=mod;
return ansl;
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)
{
int a;
scanf("%d",&a);
a++;
ade(a,i);
ade(i,a);
}
cnt=;
for(int i=;i<=q;i++)
{
int tmp;
cnt++;
dt[cnt].no=i;
dt[cnt].lft=true;
scanf("%d",&dt[cnt].rgt);
cnt++;
dt[cnt].no=i;
dt[cnt].lft=false;
scanf("%d",&dt[cnt].rgt);
dt[cnt].rgt++;
scanf("%d",&tmp);
tmp++;
dt[cnt].z=dt[cnt-].z=tmp;
}
sort(dt+,dt+cnt+,cmp);
Basic_dfs(,);
Build_dfs(,);
int plc=;
for(int i=;i<=cnt;i++)
{
while(plc<=dt[i].rgt)
{
Insert(plc);
plc++;
}
int x=dt[i].no;
int pl=dt[i].z;
lnt tmp=Val(pl);
if(dt[i].lft)
tmp=-tmp;
ans[x]=(ans[x]+tmp)%mod;
}
for(int i=;i<=q;i++)
printf("%lld\n",(ans[i]%mod+mod)%mod);
return ;
}
BZOJ3626: [LNOI2014]LCA(树链剖分+线段树)的更多相关文章
- 【bzoj3626】[LNOI2014]LCA 树链剖分+线段树
题目描述 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1.设dep[i]表示点i的深度,LCA(i,j)表示i与j的最近公共祖先.有q次询问,每次询 ...
- 【BZOJ-2325】道馆之战 树链剖分 + 线段树
2325: [ZJOI2011]道馆之战 Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 1153 Solved: 421[Submit][Statu ...
- Aizu 2450 Do use segment tree 树链剖分+线段树
Do use segment tree Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.bnuoj.com/v3/problem_show ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- BZOJ3862Little Devil I——树链剖分+线段树
题目大意: 给一棵树,每条边可能是黑色或白色(起始都是白色),有三种操作: 1.将u到v路径上所有边颜色翻转(黑->白,白->黑) 2.将只有一个点在u到v路径上的边颜色翻转 3.查询u到 ...
- BZOJ2325[ZJOI2011]道馆之战——树链剖分+线段树
题目描述 口袋妖怪(又名神奇宝贝或宠物小精灵)红/蓝/绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中 的每一个冰块都只能经过一次.当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才 ...
- BZOJ2819Nim——树链剖分+线段树+Nim游戏
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 )
POJ.2763 Housewife Wind ( 边权树链剖分 线段树维护区间和 ) 题意分析 给出n个点,m个询问,和当前位置pos. 先给出n-1条边,u->v以及边权w. 然后有m个询问 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- [HDU3710] Battle Over Cities [树链剖分+线段树+并查集+kruskal+思维]
题面 一句话题意: 给定一张 N 个点, M 条边的无向连通图, 每条边上有边权 w . 求删去任意一个点后的最小生成树的边权之和. 思路 首先肯定要$kruskal$一下 考虑$MST$里面去掉一个 ...
随机推荐
- 一个工作快八年的老IT人士这几年沉浮总结的职场经验教训
曾经我挺喜欢写博客,认为把心中的想法表达出来非常畅快.而且还能和网上非常多人沟通交流,如今我更喜欢把想法留在心中.博客非常久没更新了,刚才闲来无事.看看职场话题版块发现非常多人都挺迷茫的,所以我写一些 ...
- scikit-learn:3.2. Grid Search: Searching for estimator parameters
參考:http://scikit-learn.org/stable/modules/grid_search.html GridSearchCV通过(蛮力)搜索參数空间(參数的全部可能组合).寻找最好的 ...
- OpenCV【2】---读取png图片显示到QT label上的问题
问题一: 操作图片test.png是一个365x365的PNG图片 通过OpenCV自带的GUI显示出来图像是没问题的,例如以下操作代码所看到的: QStringfileName=QFileD ...
- 分贝(dB)的理解
分贝(dB,decibels)表达的是功率比(power ratio,P2/P1),而不是一个amount,P2>P1,分贝为正值,否则为负值.分贝是对数形式的,而不是线性形式的,也即 20 d ...
- HDU2665 kth number 线段树做法
题意:求区间第k小 思路: 线段树 每个节点上保存 当前区间已经排序好的序列 (归并一下就好了嘛 复杂度 O(l)的) 这样建树的时空复杂度都是 O(nlogn)的 对于 每次询问 二分一个答案 在树 ...
- LDAP实现企业异构平台的统一认证
LDAP实现企业异构平台的统一认证 技术是为应用服务的,没有应用,技术就无用武之地.同样光配置完LDAP服务器没有任何意义,只有把所有需要认证的环节,只有纳入LDAP系统中,才能使它发挥应有 ...
- ORA-01659: 无法分配超出 7 的 MINEXTENTS
plsql连接出错:ORA-01659: 无法分配超出 7 的 MINEXTENTS (在表空间 PERFSTAT 中) 从 Oracle Database 10g Enterprise Editio ...
- try/catch的用法
1.try/catch用法基础介绍 try { //程序中抛出异常 throw value; } catch(valuetype v) { //例外处理程序段 } 语法小结:throw抛出值,catc ...
- NET 高效开发之不可错过的实用工具(第一的当然是ReSharper插件)
工欲善其事,必先利其器,没有好的工具,怎么能高效的开发出高质量的代码呢?本文为 ASP.NET 开发者介绍一些高效实用的工具,包括 SQL 管理,VS插件,内存管理,诊断工具等,涉及开发过程的各个环节 ...
- Mysql数据库常规操作(建表、查询)
一.表单操作 1-1.创建表 create table tb_name( id in primary key auto_increment); 1-2.查看表 desc table_name; ...