bzoj3626: [LNOI2014]LCA奇技淫巧+树剖+线段树
题目求[a,b]到c的lca深度之和 显然是一个满足区间减法的操作
于是简化为
[1,b]到c的lca深度之和
(然并卵╮(╯▽╰)╭)然后就用奇技淫巧发现
a和b的lca深度=先把根节点到a的路径都染色,然后查根节点到b的路径上染色点数
只要把染色改为权值+1,就可以轻易解决区间的问题
方法显然:离线,把询问排序,维护一棵兹磁区间加法和区间求和的线段树即可轻易解决
1 #include <bits/stdc++.h> 2 #define mid ((l+r)>>1) 3 #define mod 201314 4 using namespace std; 5 int n,m,N,M,an,p,q,o; 6 int size[50001],fa[50001],top[50001],pos[50001],son[50001],bro[50001],l[50001],r[50001],ans[100001]; 7 int sum[200001],flag[200001]; 8 struct quer 9 { 10 int r,x,bel; 11 } que[100001]; 12 bool operator<(quer a,quer b){ return a.r<b.r;} 13 void ins(int a,int b,int c) 14 { 15 que[++N].r=a; 16 que[N].x=b; 17 que[N].bel=c; 18 } 19 int build(int now) 20 { 21 size[now]=1; 22 for(int i=son[now];i;i=bro[i]) 23 size[now]+=build(i); 24 return size[now]; 25 } 26 void pou(int now,int to) 27 { 28 int ma=0,id=0;top[now]=to;pos[now]=++M; 29 for(int i=son[now];i;i=bro[i]) 30 if(size[i]>ma) ma=size[i],id=i; 31 if(id) pou(id,to); 32 for(int i=son[now];i;i=bro[i]) 33 if(i!=id) pou(i,i); 34 } 35 void push(int now,int l,int r) 36 { 37 if(flag[now] && l!=r) 38 { 39 sum[now*2]+=(mid-l+1)*flag[now]; 40 sum[now*2]%=mod; 41 sum[now*2+1]+=(r-mid)*flag[now]; 42 sum[now*2]%=mod; 43 flag[now*2]+=flag[now]; 44 flag[now*2]%=mod; 45 flag[now*2+1]+=flag[now]; 46 flag[now*2+1]%=mod; 47 flag[now]=0; 48 } 49 } 50 void add(int now,int l,int r,int x,int y) 51 { 52 if(l==x && r==y) 53 { 54 sum[now]+=r-l+1;flag[now]+=1; 55 sum[now]%=mod; 56 return; 57 } 58 push(now,l,r); 59 if(x<=mid) add(now*2,l,mid,x,min(mid,y)); 60 if(y>mid) add(now*2+1,mid+1,r,max(x,mid+1),y); 61 sum[now]=sum[now*2]+sum[now*2+1]; 62 } 63 int query(int now,int l,int r,int x,int y) 64 { 65 if(l==x && r==y) 66 return sum[now]; 67 push(now,l,r); 68 int ans=0; 69 if(x<=mid) ans+=query(now*2,l,mid,x,min(mid,y)); 70 if(y>mid) ans+=query(now*2+1,mid+1,r,max(x,mid+1),y); 71 return ans; 72 } 73 void link(int now) 74 { 75 for(;now;now=fa[top[now]]) 76 add(1,1,M,pos[top[now]],pos[now]); 77 } 78 int qu(int now) 79 { 80 for(an=0;now;now=fa[top[now]]) 81 an=(an+query(1,1,M,pos[top[now]],pos[now]))%mod; 82 return an; 83 } 84 int main() 85 { 86 scanf("%d%d",&n,&m); 87 for(int i=2;i<=n;i++) 88 scanf("%d",&fa[i]),++fa[i], 89 bro[i]=son[fa[i]],son[fa[i]]=i; 90 build(1);pou(1,1); 91 for(int i=1;i<=m;i++) 92 { 93 scanf("%d%d%d",&p,&q,&o); 94 l[i]=p;r[i]=++q;++o; 95 if(p)ins(p,o,i);ins(q,o,i); 96 } 97 sort(que+1,que+N+1); 98 int now=0; 99 for(int i=1;i<=N;i++) 100 { 101 while(que[i].r>now) link(++now); 102 int ret=qu(que[i].x); 103 if(now==l[que[i].bel]) 104 ans[que[i].bel]-=ret; 105 else 106 ans[que[i].bel]+=ret; 107 } 108 for(int i=1;i<=m;i++) 109 printf("%d\n",(ans[i]+mod)%mod); 110 return 0; 111 }