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 }

 

posted @ 2017-02-21 19:51  汪立超  阅读(616)  评论(0编辑  收藏  举报