题目求[a,b]到c的lca深度之和   显然是一个满足区间减法的操作

于是简化为

[1,b]到c的lca深度之和

(然并卵╮(╯▽╰)╭)然后就用奇技淫巧发现

a和b的lca深度=先把根节点到a的路径都染色,然后查根节点到b的路径上染色点数

只要把染色改为权值+1,就可以轻易解决区间的问题

方法显然:离线,把询问排序,维护一棵兹磁区间加法和区间求和的线段树即可轻易解决

 #include <bits/stdc++.h>
#define mid ((l+r)>>1)
#define mod 201314
using namespace std;
int n,m,N,M,an,p,q,o;
int size[],fa[],top[],pos[],son[],bro[],l[],r[],ans[];
int sum[],flag[];
struct quer
{
int r,x,bel;
} que[];
bool operator<(quer a,quer b){ return a.r<b.r;}
void ins(int a,int b,int c)
{
que[++N].r=a;
que[N].x=b;
que[N].bel=c;
}
int build(int now)
{
size[now]=;
for(int i=son[now];i;i=bro[i])
size[now]+=build(i);
return size[now];
}
void pou(int now,int to)
{
int ma=,id=;top[now]=to;pos[now]=++M;
for(int i=son[now];i;i=bro[i])
if(size[i]>ma) ma=size[i],id=i;
if(id) pou(id,to);
for(int i=son[now];i;i=bro[i])
if(i!=id) pou(i,i);
}
void push(int now,int l,int r)
{
if(flag[now] && l!=r)
{
sum[now*]+=(mid-l+)*flag[now];
sum[now*]%=mod;
sum[now*+]+=(r-mid)*flag[now];
sum[now*]%=mod;
flag[now*]+=flag[now];
flag[now*]%=mod;
flag[now*+]+=flag[now];
flag[now*+]%=mod;
flag[now]=;
}
}
void add(int now,int l,int r,int x,int y)
{
if(l==x && r==y)
{
sum[now]+=r-l+;flag[now]+=;
sum[now]%=mod;
return;
}
push(now,l,r);
if(x<=mid) add(now*,l,mid,x,min(mid,y));
if(y>mid) add(now*+,mid+,r,max(x,mid+),y);
sum[now]=sum[now*]+sum[now*+];
}
int query(int now,int l,int r,int x,int y)
{
if(l==x && r==y)
return sum[now];
push(now,l,r);
int ans=;
if(x<=mid) ans+=query(now*,l,mid,x,min(mid,y));
if(y>mid) ans+=query(now*+,mid+,r,max(x,mid+),y);
return ans;
}
void link(int now)
{
for(;now;now=fa[top[now]])
add(,,M,pos[top[now]],pos[now]);
}
int qu(int now)
{
for(an=;now;now=fa[top[now]])
an=(an+query(,,M,pos[top[now]],pos[now]))%mod;
return an;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
scanf("%d",&fa[i]),++fa[i],
bro[i]=son[fa[i]],son[fa[i]]=i;
build();pou(,);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&p,&q,&o);
l[i]=p;r[i]=++q;++o;
if(p)ins(p,o,i);ins(q,o,i);
}
sort(que+,que+N+);
int now=;
for(int i=;i<=N;i++)
{
while(que[i].r>now) link(++now);
int ret=qu(que[i].x);
if(now==l[que[i].bel])
ans[que[i].bel]-=ret;
else
ans[que[i].bel]+=ret;
}
for(int i=;i<=m;i++)
printf("%d\n",(ans[i]+mod)%mod);
return ;
}

最新文章

  1. 【AR实验室】ARToolKit之制作自己的Marker/NFT
  2. 学习SpringMVC——从HelloWorld开始
  3. 深入研究java.lang.Runtime类
  4. 005.TCP--拼接TCP头部IP头部,实现TCP三次握手的第一步(Linux,原始套接字)
  5. 26Mybatis_一级缓存及其测试
  6. Linux查询网址
  7. php 添加redis扩展(二)
  8. windows下搭建属于自己的web服务器
  9. HDU 4430 Yukari&#39;s Birthday (二分+枚举)
  10. thinkphp 3.2.3 入门示例
  11. 二叉树3种递归和非递归遍历(Java)
  12. 《JavaScript高级程序设计》读书笔记 ---RegExp 类型
  13. C++第二天学习
  14. PHP连接mysql数据库进行增删改查--删除
  15. Linux显示系统的诊断信息
  16. semver(Semantic Versioning)
  17. ng-model,ng-value,ng-bind,{{}}----angularJS数据绑定
  18. 微信公众平台开发者中心服务器配置Token验证失败问题
  19. linux下的nmap工具能干什么?
  20. 我的github地址

热门文章

  1. user版本如何永久性开启adb 的root权限【转】
  2. jenkins页面不刷新,设置tomcat缓存
  3. ffmpeg av_interleaved_write_frame Operation not permitted
  4. 关于Spring MVC分页
  5. 理解 Android Fragment
  6. bzoj 2155 Xor
  7. python 基础之第三天
  8. java并发之阻塞队列LinkedBlockingQueue与ArrayBlockingQueue
  9. vim opencv
  10. sql之索引