bzoj 3626 LCA

题目大意:

给出一个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的最近公共祖先的深度之和)

思路:

lca可以用类似于差分的思路来维护:

若求x和y的LCA的深度 可以把x到根上的路径上的每个点的权值+1 

然后求y到根上所有点的权值和就行了,这样恰好能表示LCA的深度

这样我们就可以把所有l和r离线下来排序

然后按照1 - n 的顺序logn修改每个点到根的路径上的点权

然后查询

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstdlib>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<queue>
  9 #define inf 2139062143
 10 #define ll long long
 11 #define MAXN 50101
 12 #define MOD 201314
 13 using namespace std;
 14 inline int read()
 15 {
 16     int x=0,f=1;char ch=getchar();
 17     while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
 18     while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();}
 19     return x*f;
 20 }
 21 int n,z[MAXN],ans[MAXN];
 22 int Cnt,cnt[MAXN],bl[MAXN],fa[MAXN],hsh[MAXN];
 23 int fst[MAXN],nxt[MAXN<<1],to[MAXN<<1];
 24 struct data {int l,r,sum,tag;}tr[MAXN<<2];
 25 struct Qst {int num,pos;bool f;}g[MAXN<<1];
 26 bool cmp(Qst a,Qst b) {return a.pos<b.pos;}
 27 void add(int u,int v) {nxt[++Cnt]=fst[u],fst[u]=Cnt,to[Cnt]=v;}
 28 void dfs(int x)
 29 {
 30     cnt[x]=1;
 31     for(int i=fst[x];i;i=nxt[i])
 32     {
 33         if(to[i]==fa[x]) continue;
 34         dfs(to[i]);
 35         cnt[x]+=cnt[to[i]];
 36     }
 37 }
 38 void Dfs(int x,int anc)
 39 {
 40     bl[x]=anc,hsh[x]=++Cnt;
 41     int hvs=0;
 42     for(int i=fst[x];i;i=nxt[i])
 43         if(to[i]!=fa[x]&&cnt[to[i]]>cnt[hvs]) hvs=to[i];
 44     if(!hvs) return ;
 45     Dfs(hvs,anc);
 46     for(int i=fst[x];i;i=nxt[i])
 47         if(to[i]!=fa[x]&&to[i]!=hvs) Dfs(to[i],to[i]);
 48 }
 49 void build(int k,int l,int r)
 50 {
 51     tr[k].l=l,tr[k].r=r,tr[k].sum=tr[k].tag=0;
 52     if(l==r) return ;
 53     int mid=(l+r)>>1;
 54     build(k<<1,l,mid);
 55     build(k<<1|1,mid+1,r);
 56 }
 57 void pshd(int k)
 58 {
 59     tr[k<<1].tag=tr[k].tag+tr[k<<1].tag;tr[k<<1|1].tag+=tr[k].tag;
 60     tr[k<<1].sum+=(tr[k<<1].r-tr[k<<1].l+1)*tr[k].tag,tr[k<<1|1].sum+=(tr[k<<1|1].r-tr[k<<1|1].l+1)*tr[k].tag;
 61     tr[k].tag=0;
 62 }
 63 void upd(int k,int a,int b)
 64 {
 65     int l=tr[k].l,r=tr[k].r;
 66     if(a==l&&b==r) {tr[k].sum+=r-l+1,tr[k].tag++;return ;}
 67     if(tr[k].tag) pshd(k);
 68     int mid=(l+r)>>1;
 69     if(mid>=b) upd(k<<1,a,b);
 70     else if(mid<a) upd(k<<1|1,a,b);
 71     else {upd(k<<1,a,mid);upd(k<<1|1,mid+1,b);}
 72     tr[k].sum=tr[k<<1].sum+tr[k<<1|1].sum;
 73 }
 74 int query(int k,int a,int b)
 75 {
 76     int l=tr[k].l,r=tr[k].r;
 77     if(a==l&&b==r) return tr[k].sum%MOD;
 78     int mid=(l+r)>>1;
 79     if(tr[k].tag) pshd(k);
 80     if(mid>=b) return query(k<<1,a,b)%MOD;
 81     else if(mid<a) return query(k<<1|1,a,b)%MOD;
 82     else return (query(k<<1,a,mid)+query(k<<1|1,mid+1,b))%MOD;
 83 }
 84 void Fill(int x)
 85 {
 86     while(bl[x]!=1)
 87     {
 88         upd(1,hsh[bl[x]],hsh[x]);
 89         x=fa[bl[x]];
 90     }
 91     upd(1,1,hsh[x]);
 92 }
 93 int Query(int x)
 94 {
 95     int res=0;
 96     while(bl[x]!=1)
 97     {
 98         (res+=query(1,hsh[bl[x]],hsh[x]))%=MOD;
 99         x=fa[bl[x]];
100     }
101     (res+=query(1,1,hsh[x]))%=MOD;
102     return res;
103 }
104 int main()
105 {
106     n=read();int l,r,t,now=1,T=read();
107     for(int i=2;i<=n;i++) {fa[i]=read()+1;add(i,fa[i]);add(fa[i],i);}
108     fa[1]=1,Cnt=0;
109     dfs(1);Dfs(1,1);build(1,1,n);
110     for(int i=1;i<=T;i++) 
111     {
112         l=read(),r=read()+1,z[i]=read()+1;
113         g[2*i].num=g[2*i-1].num=i;
114         g[2*i-1].pos=l,g[2*i].pos=r;
115         g[2*i-1].f=0,g[2*i].f=1;
116     }
117     sort(g+1,g+2*T+1,cmp);
118     for(int i=1;i<=2*T;i++)
119     {
120         if(!g[i].pos) continue;
121         while(now<=g[i].pos)
122         {
123             Fill(now);
124             now++;
125         }
126         if(!g[i].f) ans[g[i].num]=0-Query(z[g[i].num]);
127         else ans[g[i].num]+=Query(z[g[i].num]);
128     }
129     for(int i=1;i<=T;i++) printf("%d\n",(ans[i]+MOD)%MOD);
130 }
View Code

又一次因为bool导致了1+1=1 

posted @ 2018-01-26 14:04  jack_yyc  阅读(126)  评论(0编辑  收藏  举报