【JLOI2014】松鼠的新家
这道题洛谷给的标签是LCA,线段树,树链剖分。
当然LCA+树上差分能通过这道题,但出现在树链剖分当中,我决定用树链剖分解决
显然这是一道裸的树链剖分。树剖之后进行区间修改,单点查询操作。(这道题线段树都不用build……23333)
我们按照题目给的顺序给这一棵"树"放上糖果,当然注意重复的部分要减掉,最后对每一个点进行查询即可。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 typedef long long ll; 5 #define N 300010 6 inline int read() { 7 int ret=0,f=1; 8 char c=getchar(); 9 while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();} 10 while(c<='9'&&c>='0') ret=ret*10+c-'0',c=getchar(); 11 return ret*f; 12 } 13 using namespace std; 14 int n; 15 struct edge { 16 int next,to; 17 }a[N<<1]; 18 int num,head[N<<1]; 19 int fa[N],son[N],top[N],d[N],seg[N],rev[N],tot; 20 int sum[N<<2],tag[N<<2],size[N]; 21 int turn[N]; 22 inline void add(int from,int to) { 23 a[++num].next=head[from]; a[num].to=to; head[from]=num; 24 swap(from,to); 25 a[++num].next=head[from]; a[num].to=to; head[from]=num; 26 } 27 void dfs1(int u,int f) { 28 size[u]=1; 29 fa[u]=f; 30 d[u]=d[f]+1; 31 for(int i=head[u];i;i=a[i].next) { 32 int v=a[i].to; 33 if(v==f) continue ; 34 dfs1(v,u); 35 size[u]+=size[v]; 36 if(size[v]>size[son[u]]) son[u]=v; 37 } 38 } 39 void dfs2(int u,int f) { 40 if(son[u]) { 41 seg[son[u]]=++tot; 42 rev[tot]=son[u]; 43 top[son[u]]=top[u]; 44 dfs2(son[u],u); 45 } 46 for(int i=head[u];i;i=a[i].next) { 47 int v=a[i].to; 48 if(!top[v]) { 49 seg[v]=++tot; 50 rev[tot]=v; 51 top[v]=v; 52 dfs2(v,u); 53 } 54 } 55 } 56 inline void pushdown(int now,int len) { 57 if(!tag[now]) return ; 58 tag[now<<1]+=tag[now]; 59 tag[now<<1|1]+=tag[now]; 60 sum[now<<1]+=tag[now]*(len-(len>>1)); 61 sum[now<<1|1]+=tag[now]*(len>>1); 62 tag[now]=0; 63 } 64 void updata(int now,int l,int r,int x,int y,int v) { 65 if(x<=l&&r<=y) { 66 tag[now]+=v; 67 sum[now]+=v*(r-l+1); 68 return ; 69 } 70 int mid=l+r>>1; 71 pushdown(now,r-l+1); 72 if(x<=mid) updata(now<<1,l,mid,x,y,v); 73 if(y>mid) updata(now<<1|1,mid+1,r,x,y,v); 74 sum[now]=sum[now<<1]+sum[now<<1|1]; 75 } 76 void find(int x,int y) { 77 while(top[x]!=top[y]) { 78 if(d[top[x]]<d[top[y]]) swap(x,y); 79 updata(1,1,tot,seg[top[x]],seg[x],1); 80 x=fa[top[x]]; 81 } 82 if(d[x]>d[y]) swap(x,y); 83 updata(1,1,tot,seg[x],seg[y],1); 84 } 85 int query(int now,int l,int r,int x) { 86 if(l==r) return sum[now]; 87 int mid=l+r>>1; 88 pushdown(now,r-l+1); 89 if(x<=mid) return query(now<<1,l,mid,x); 90 else return query(now<<1|1,mid+1,r,x); 91 } 92 int main() { 93 n=read(); 94 for(int i=1;i<=n;i++) turn[i]=read(); 95 for(int i=1;i<n;i++) add(read(),read()); 96 dfs1(1,0); 97 tot=seg[1]=rev[1]=top[1]=1; 98 dfs2(1,0); 99 // build(1,1,tot); 100 for(int i=1;i<n;i++) { 101 find(turn[i],turn[i+1]); 102 updata(1,1,tot,seg[turn[i+1]],seg[turn[i+1]],-1); 103 } 104 for(int i=1;i<=n;i++) { 105 printf("%d\n",query(1,1,tot,seg[i])); 106 } 107 return 0; 108 }