树链剖分 [JLOI2014]松鼠的新家

 [JLOI2014]松鼠的新家

时间限制: 1 Sec  内存限制: 128 MB

题目描述

松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的。天哪,他居然真的住在“树”上。松鼠想邀请****前来参观,并且还指定一份参观指南,他希望**能够按照他的指南顺序,先去a1,再去a2,……,最后到an,去参观新家。
可是这样会导致**重复走很多房间,懒惰的**不听地推辞。可是松鼠告诉他,每走到一个房间,他就可以从房间拿一块糖果吃。**是个馋家伙,立马就答应了。
现在松鼠希望知道为了保证**有糖果吃,他需要在每一个房间各放至少多少个糖果。因为松鼠参观指南上的最后一个房间an是餐厅,餐厅里他准备了丰盛的大餐,所以当**在参观的最后到达餐厅时就不需要再拿糖果吃了。

输入

第一行一个整数n,表示房间个数
第二行n个整数,依次描述a1-an
接下来n-1行,每行两个整数x,y,表示标号x和y的两个房间之间有树枝相连。

输出

一共n行,第i行输出标号为i的房间至少需要放多少个糖果,才能让**有糖果吃。

样例输入

5
1 4 5 3 2
1 2
2 4
2 3
4 5
 

样例输出

1
2
1
2
1
 

提示

2<= n <=300000

  树链剖分裸题,全当复习了。

  首先既然是在树上,那么两点之间的路径就是唯一的了,果断树剖,其实LCA也可以,不过时间复杂度貌似并不允许,所以放弃。

  首先,可以明确的是,我们直接从a[1]点位出发一定是最优的,不知道Q某犇为啥会纠结这个,然后就是慢慢慢慢的树剖了,然后就是一两个坑点,首先,虽然每一次树剖都是从a[i]~a[i+1],但a[i]早在求a[i-1]~a[i]时算过了,所以当我们最后输出的时候一定要记得把a[2~n]的结果-1。为什么要把a[n]的结果也减一呢?读题,a[n]是餐厅,因此不必放糖,但这并不意味着来回经过不必放糖,所以在最后一起减掉就好了。

  

  1 #include<iostream>
  2 #include<cstdlib>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<algorithm>
  6 #include<map>
  7 #include<queue>
  8 #include<string>
  9 #include<cmath>
 10 # define N 300005
 11 using namespace std;
 12 int n;
 13 int b[300005],a[300004];
 14 struct ro{
 15     int to;
 16     int next;
 17 }road[1000005];
 18 int zz;
 19 void build(int x,int y){
 20     zz++;
 21     road[zz].to=y;
 22     road[zz].next=a[x];
 23     a[x]=zz;
 24 }
 25 int deep[N],fa[N],hson[N],size[N];
 26 void dfs(int x,int dep){
 27     deep[x]=dep;
 28     size[x]=1;
 29     for(int i=a[x];i>0;i=road[i].next)
 30     {
 31         int y=road[i].to;
 32         if(fa[x]==y)continue;
 33         fa[y]=x;
 34         dfs(y,dep+1);
 35         size[x]+=size[y];
 36         if(size[hson[x]]<size[y])
 37             hson[x]=y;
 38     }
 39 }
 40 int zz2;
 41 int f2[N],dl[N],dfn[N];
 42 void dfs2(int x,int top){
 43     f2[x]=top;
 44     zz2++;
 45     dl[zz2]=x;
 46     dfn[x]=zz2;
 47     if(hson[x]) dfs2(hson[x],top);
 48     for(int i=a[x];i>0;i=road[i].next)
 49     {
 50         int y=road[i].to;
 51         if(y==fa[x]||y==hson[x]) continue;
 52         dfs2(y,y);
 53     }
 54 }
 55 struct no{
 56     int sum;
 57     int lazy;
 58     int right,left;
 59     int mid;
 60 }node[4*N];
 61 void build(int left,int right,int x){
 62     node[x].left=left;
 63     node[x].right=right;
 64     if(left==right)
 65     {
 66         return;
 67     }
 68     int mid=(left+right)/2;
 69     node[x].mid=mid;
 70     build(left,mid,2*x);
 71     build(mid+1,right,2*x+1);
 72 }
 73 void pushdown(int x){
 74     if(node[x].lazy)
 75     {
 76         node[2*x].lazy+=node[x].lazy;
 77         node[2*x+1].lazy+=node[x].lazy;
 78         node[x*2].sum+=node[x].lazy;
 79         node[2*x+1].sum+=node[x].lazy;
 80         node[x].lazy=0;
 81     }
 82 }
 83 void add(int left,int right,int x){
 84     if(node[x].left==left&&node[x].right==right)
 85     {
 86         node[x].sum++;
 87         node[x].lazy++;
 88         return;
 89     }
 90     pushdown(x);
 91     int mid=node[x].mid;
 92     if(right<=mid)
 93     {
 94         add(left,right,2*x);
 95     }
 96     else if(mid<left)
 97     {
 98         add(left,right,2*x+1);
 99     }
100     else
101     {
102         add(left,mid,2*x);
103         add(mid+1,right,2*x+1);
104     }
105     node[x].sum=node[x*2].sum+node[2*x+1].sum;
106 }
107 int get(int left,int right,int x)
108 {
109     if(node[x].left==node[x].right)
110     {
111         return node[x].sum;
112     }
113     pushdown(x);
114     int mid=node[x].mid;
115     if(left<=mid)
116         return get(left,right,2*x);
117     else
118         return get(left,right,2*x+1);
119 }
120 void change(int x,int y){
121      
122     int fx=f2[x],fy=f2[y];
123     while(fx!=fy)
124     {
125         if(deep[fx]<deep[fy])
126         {
127             swap(fx,fy);
128             swap(x,y);
129         }
130         add(dfn[fx],dfn[x],1);
131         x=fa[fx];
132         fx=f2[x];
133     }
134      
135     if(deep[y]<deep[x]) swap(y,x);
136     if(dfn[x]<=dfn[y])
137         add(dfn[x],dfn[y],1);
138      
139 }
140 int main(){
141     scanf("%d",&n);
142     for(int i=1;i<=n;i++)
143         scanf("%d",&b[i]);
144     for(int i=1;i<n;i++)
145     {
146         int x,y;
147         scanf("%d%d",&x,&y);
148         build(x,y);
149         build(y,x);
150     }
151     dfs(1,1);
152     dfs2(1,1);
153     build(1,n,1);
154     for(int i=2;i<=n;i++)
155     {
156         change(b[i-1],b[i]);
157     }
158     for(int i=1;i<=n;i++)
159     {
160         //cout<<endl;
161         int x=get(dfn[i],dfn[i],1);
162         if(i!=b[1])
163             x--;
164         printf("%d
",x);
165     }
166     //while(1);
167     return 0;
168 }
View Code
原文地址:https://www.cnblogs.com/liutianrui/p/7351671.html