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 }
又一次因为bool导致了1+1=1