NewTrain6 A (bzoj3631) 松鼠的新家 树剖/lca

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2560  Solved: 1357
[Submit][Status][Discuss]

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

1
2
1
2
1

HINT

2<= n <=300000

 

题目大意:给定一棵n个节点的树和一个1~n的排列ai,对于每一个i,给从ai到ai+1的路径上除了起点以外的点都加上1,求每个点最终的值

 

题解:

看到题就感觉像树剖,于是就直接套板子上了。每次对于一条链来说,给左端点加上1,右端点的下一位减去1,最后做一个前缀和。注意每次是不给起点+1的,因此最后给除了a1以外的点全部-1就好了

 

代码:

 

  1 #include<cmath>
  2 #include<math.h>
  3 #include<ctype.h>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<cassert>
  7 #include<cctype>
  8 #include<cerrno>
  9 #include<cfloat>
 10 #include<ciso646>
 11 #include<climits>
 12 #include<clocale>
 13 #include<complex>
 14 #include<csetjmp>
 15 #include<csignal>
 16 #include<cstdarg>
 17 #include<cstddef>
 18 #include<cstdio>
 19 #include<cstdlib>
 20 #include<cstring>
 21 #include<ctime>
 22 #include<cwchar>
 23 #include<cwctype>
 24 #include<deque>
 25 #include<exception>
 26 #include<fstream>
 27 #include<functional>
 28 #include<iomanip>
 29 #include<ios>
 30 #include<iosfwd>
 31 #include<iostream>
 32 #include<istream>
 33 #include<iterator>
 34 #include<limits>
 35 #include<list>
 36 #include<locale>
 37 #include<map>
 38 #include<memory>
 39 #include<new>
 40 #include<numeric>
 41 #include<ostream>
 42 #include<queue>
 43 #include<set>
 44 #include<sstream>
 45 #include<stack>
 46 #include<stdexcept>
 47 #include<streambuf>
 48 #include<string>
 49 #include<typeinfo>
 50 #include<utility>
 51 #include<valarray>
 52 #include<vector>
 53 #include<string.h>
 54 #include<stdlib.h>
 55 #include<stdio.h>
 56 using namespace std;
 57 
 58 typedef long long ll;
 59 
 60 #define pb push_back
 61 #define mp make_pair
 62 #define x first
 63 #define y second
 64 
 65 const ll inf=2147483647;
 66 
 67 //
 68 
 69 ll read()
 70 {
 71     ll x=0,f=1;
 72     char ch=getchar();
 73     while(ch<'0'||ch>'9')
 74     {
 75         if(ch=='-')f=-1;
 76         ch=getchar();
 77     }
 78     while(ch>='0'&&ch<='9')
 79     {
 80         x=x*10+ch-'0';
 81         ch=getchar();
 82     }
 83     return x*f;
 84 }
 85 
 86 void print(ll x)
 87 {
 88     if(x<0)putchar('-'),x=-x;
 89     short a[20]= {},sz=0;
 90     while(x>0)a[sz++]=x%10,x/=10;
 91     if(sz==0)putchar('0');
 92     for(ll i=sz-1; i>=0; i--)putchar('0'+a[i]);
 93 }
 94 
 95 const ll mod=1e9+7;
 96 
 97 int n;
 98 int a[333333];
 99 vector<int> adj[333333];
100 
101 int fa[333333];
102 int dep[333333];
103 int sz[333333];
104 int son[333333];
105 int tp[333333];
106 int num[333333];
107 int rnk[333333];
108 int cnt;
109 
110 void dfs1(int nw,int pa,int d){
111     fa[nw]=pa;
112     dep[nw]=d;
113     sz[nw]=1;
114     for(int i=0;i<adj[nw].size();i++){
115         int v=adj[nw][i];
116         if(v==pa) continue;
117         dfs1(v,nw,d+1);
118         if(son[nw]==0 || sz[son[nw]]<sz[v]) son[nw]=v;
119         sz[nw]+=sz[v];
120     }
121 }
122 
123 void dfs2(int nw,int t){
124     tp[nw]=t;
125     num[nw]=++cnt;
126     rnk[cnt]=nw;
127 
128     if(son[nw]==0) return;
129     dfs2(son[nw],t);
130 
131     for(int i=0;i<adj[nw].size();i++){
132         int v=adj[nw][i];
133         if(v==fa[nw] || v==son[nw]) continue;
134         dfs2(v,v);
135     }
136 }
137 
138 int root;
139 void doit(){
140     //树链剖分
141     root=a[1];
142     dfs1(root,-1,0);
143     dfs2(root,root);
144 /*
145     for(int i=1;i<=cnt;i++)
146         cout<<rnk[i]<<' ';
147     cout<<endl;*/
148 }
149 
150 int ans[333333];
151 
152 inline void add(int a,int b){
153     //cout<<a<<' '<<b<<endl;
154     if(a>b) swap(a,b);
155     ans[a]++;
156     ans[b+1]--;
157 }
158 
159 void update_path(int x,int y){
160     int fx=tp[x],fy=tp[y];
161     while(fx!=fy){
162         if(dep[fx]>=dep[fy]){
163             add(num[fx],num[x]);
164             x=fa[fx];
165         }
166         else{
167             add(num[fy],num[y]);
168             y=fa[fy];
169         }
170         fx=tp[x];
171         fy=tp[y];
172     }
173     add(num[x],num[y]);
174 }
175 
176 int main(){
177     //freopen("in","r",stdin);
178     n=read();
179     for(int i=1;i<=n;i++)
180         a[i]=read();
181     for(int i=1;i<n;i++){
182         int a=read(),b=read();
183         adj[a].pb(b);adj[b].pb(a);
184     }
185 
186     doit();
187 
188     for(int i=1;i<n;i++){
189         update_path(a[i],a[i+1]);
190     }
191 
192     for(int i=1;i<=n;i++){
193         ans[i]+=ans[i-1];
194     }
195     for(int i=2;i<=n;i++)
196         ans[i]--;
197 
198     for(int i=1;i<=n;i++){
199         printf("%d\n",ans[num[i]]);
200     }
201 
202     return 0;
203 }
204 
205 /*
206 5
207 1 4 5 3 2
208 1 2
209 2 4
210 2 3
211 4 5
212  */
View Code

 

 

 

然后就发现自己做烦了。

我都想到了给左端点加1右端点减1了,就没想到树上也能这样做

每次操作,给两个端点都加上1,然后给他们的lca减去1,lca的父亲也减去1,然后在dfs一下,每个点的权值加上他的儿子们的权值。注意,输出时所有的点的权值-1,原因同上

 

代码:

 

  1 #include<cmath>
  2 #include<math.h>
  3 #include<ctype.h>
  4 #include<algorithm>
  5 #include<bitset>
  6 #include<cassert>
  7 #include<cctype>
  8 #include<cerrno>
  9 #include<cfloat>
 10 #include<ciso646>
 11 #include<climits>
 12 #include<clocale>
 13 #include<complex>
 14 #include<csetjmp>
 15 #include<csignal>
 16 #include<cstdarg>
 17 #include<cstddef>
 18 #include<cstdio>
 19 #include<cstdlib>
 20 #include<cstring>
 21 #include<ctime>
 22 #include<cwchar>
 23 #include<cwctype>
 24 #include<deque>
 25 #include<exception>
 26 #include<fstream>
 27 #include<functional>
 28 #include<iomanip>
 29 #include<ios>
 30 #include<iosfwd>
 31 #include<iostream>
 32 #include<istream>
 33 #include<iterator>
 34 #include<limits>
 35 #include<list>
 36 #include<locale>
 37 #include<map>
 38 #include<memory>
 39 #include<new>
 40 #include<numeric>
 41 #include<ostream>
 42 #include<queue>
 43 #include<set>
 44 #include<sstream>
 45 #include<stack>
 46 #include<stdexcept>
 47 #include<streambuf>
 48 #include<string>
 49 #include<typeinfo>
 50 #include<utility>
 51 #include<valarray>
 52 #include<vector>
 53 #include<string.h>
 54 #include<stdlib.h>
 55 #include<stdio.h>
 56 using namespace std;
 57 
 58 typedef long long ll;
 59 
 60 #define pb push_back
 61 #define mp make_pair
 62 #define x first
 63 #define y second
 64 
 65 const ll inf=2147483647;
 66 
 67 //
 68 
 69 ll read()
 70 {
 71     ll x=0,f=1;
 72     char ch=getchar();
 73     while(ch<'0'||ch>'9')
 74     {
 75         if(ch=='-')f=-1;
 76         ch=getchar();
 77     }
 78     while(ch>='0'&&ch<='9')
 79     {
 80         x=x*10+ch-'0';
 81         ch=getchar();
 82     }
 83     return x*f;
 84 }
 85 
 86 void print(ll x)
 87 {
 88     if(x<0)putchar('-'),x=-x;
 89     short a[20]= {},sz=0;
 90     while(x>0)a[sz++]=x%10,x/=10;
 91     if(sz==0)putchar('0');
 92     for(ll i=sz-1; i>=0; i--)putchar('0'+a[i]);
 93 }
 94 
 95 const ll mod=1e9+7;
 96 
 97 int fa[21][333333];
 98 int n;
 99 int a[333333];
100 vector<int> adj[333333];
101 int tag[333333];
102 int dep[333333];
103 
104 void dfs(int nw,int pa){
105 //    cout<<nw<<' '<<pa<<endl;
106     fa[0][nw]=pa;
107     for(int i=0;i<adj[nw].size();i++){
108         int v=adj[nw][i];
109         if(v==pa) continue;
110         dep[v]=dep[nw]+1;
111         dfs(v,nw);
112     }
113 }
114 
115 inline int lca(int x,int y){
116     if(x==y) return x;
117     if(dep[x]<dep[y]) swap(x,y);
118     for(int i=19;i>=0;i--){
119         if(dep[fa[i][x]]>dep[y]) x=fa[i][x];
120     }
121     if(dep[x]>dep[y]) x=fa[0][x];
122     if(x==y) return x;
123     for(int i=19;i>=0;i--){
124         if(fa[i][x]!=fa[i][y])
125             x=fa[i][x],y=fa[i][y];
126     }
127     return fa[0][x];
128 }
129 
130 void doit(int x,int y){
131     int z=lca(x,y);
132     //cout<<x<<' '<<y<<' '<<z<<endl;
133     tag[x]++;
134     tag[y]++;
135     tag[z]--;
136     tag[fa[0][z]]--;
137 }
138 
139 void pushup(int nw){
140     for(int i=0;i<adj[nw].size();i++){
141         int v=adj[nw][i];
142         if(v==fa[0][nw]) continue;
143         pushup(v);
144         tag[nw]+=tag[v];
145     }
146 }
147 
148 void hahaha(){
149     hahaha();
150 }
151 
152 int main(){
153     //freopen("in","r",stdin);
154     //freopen("1","w",stdout);
155     n=read();
156     for(int i=1;i<=n;i++)
157         a[i]=read();
158     a[0]=a[1];
159 
160     for(int i=1;i<n;i++){
161         int fr=read(),tt=read();
162         adj[fr].pb(tt);
163         adj[tt].pb(fr);
164     }
165     adj[0].pb(a[1]);
166 
167     dfs(0,0);
168 
169     for(int i=1;i<=19;i++){
170         for(int j=1;j<=n;j++){
171             fa[i][j]=fa[i-1][fa[i-1][j]];
172         }
173     }
174 
175     for(int i=1;i<=n;i++)
176         doit(a[i-1],a[i]);
177     /*
178     for(int i=1;i<=n;i++)
179         printf("%d\n",tag[i]);
180     */
181     pushup(0);
182 
183     for(int i=1;i<=n;i++)
184         printf("%d\n",tag[i]-1);
185 
186     return 0;
187 }
View Code

 

 

 

posted @ 2018-03-25 23:35  lzt2002  阅读(135)  评论(0编辑  收藏  举报