BZOJ 3631: [JLOI2014]松鼠的新家

   太好了,第一次交就AC了,第一次这么顺利,这是一道树链剖分的题,比较容易吧!加油,相信自己,能行的。

  不过还是有点慢,跑了1900多毫秒。

  1 #include<cstdio>
  2 #include<iostream>
  3 #define rep(i,j,k) for(int i = j; i <= k; i++)
  4 #define maxn 300005
  5 using namespace std;
  6 int shun[maxn];
  7  
  8 struct node{
  9 int addv, l, r;
 10 node() {
 11    addv = l = r = 0;
 12 }
 13 } nod[maxn*4];
 14  
 15 struct edge{
 16 int to;
 17 edge* next;
 18 };
 19 edge *head[maxn], edges[maxn*2], *pt; 
 20  
 21 void add_edge(int x,int y)
 22 {
 23     pt->to = x, pt->next = head[y], head[y] = pt++;
 24     pt->to = y, pt->next = head[x], head[x] = pt++;
 25 }
 26  
 27 int read()
 28 {
 29     int s = 0, t = 1; char c = getchar();
 30     while( !isdigit(c) ){
 31         if( c == '-' ) t = -1; c = getchar();
 32     }
 33     while( isdigit(c) ){
 34         s = s * 10 + c - '0'; c = getchar();
 35     }
 36     return s * t;
 37 }
 38 int pa[maxn], top[maxn], dep[maxn], size[maxn], son[maxn];
 39 int w[maxn], tot = 0;
 40  
 41 void dfs(int now)
 42 {
 43     size[now] = 1, son[now] = 0;
 44     for(edge* i = head[now]; i; i = i->next){
 45         int to = i->to; if( to == pa[now] ) continue;
 46         pa[to] = now, dep[to] = dep[now] + 1;
 47         dfs(to); size[now] += size[to];
 48         if( size[to] > size[son[now]] ) son[now] = to;
 49     }
 50 }
 51  
 52 void dfs2(int now,int ph)
 53 {
 54     top[now] = ph, w[now] = ++tot;
 55     if( son[now] ) dfs2(son[now],ph);
 56     for(edge*i = head[now]; i; i = i->next){
 57         int to = i->to; if( to == pa[now] || to == son[now] ) continue;
 58         dfs2(to,to);
 59     } 
 60 } 
 61  
 62 void yuchu(int l,int r,int num)
 63 {
 64     nod[num].l = l, nod[num].r = r;
 65     if( l == r ){
 66         if( w[shun[1]] != l ) nod[num].addv = -1;
 67         return;
 68     }
 69     int mid = (l+r) / 2;
 70     yuchu(l,mid,num*2);
 71     yuchu(mid+1,r,num*2+1);
 72 }
 73  
 74 void update(int l,int r,int num)
 75 {
 76     int ll = nod[num].l, rr = nod[num].r;
 77     if( ll >= l && r >= rr ){
 78         nod[num].addv += 1;
 79         return ;
 80     }
 81     int mid = (ll+rr) / 2;
 82     if( r <= mid ) update(l,r,num*2);
 83     else if( l > mid ) update(l,r,num*2+1);
 84     else update(l,mid,num*2), update(mid+1,r,num*2+1);
 85 }
 86  
 87 void add(int x,int y)
 88 {
 89     while( top[x] != top[y] ){
 90         if( dep[top[x]] < dep[top[y]] ){
 91             swap(x,y);
 92         }
 93         update(w[top[x]],w[x],1);
 94         x = pa[top[x]];
 95     }
 96     if( dep[x] > dep[y] ) swap(x,y);
 97     update(w[x],w[y],1);
 98 }
 99  
100 void main_tain(int num)
101 {
102     if( !nod[num].addv ) return;
103     nod[num*2].addv += nod[num].addv;
104     nod[num*2+1].addv += nod[num].addv;
105 }
106  
107 void push(int num)
108 {
109     int l = nod[num].l, r = nod[num].r;
110     if( l == r ) {
111         w[shun[l]] = nod[num].addv;
112         return;
113     }
114     main_tain(num);
115     push(num*2), push(num*2+1);
116 }
117  
118 int main()
119 {
120     int n = read();
121     rep(i,1,n) shun[i] = read();
122     pt = edges;
123     rep(i,1,n-1){
124         int x = read(), y = read();
125         add_edge(x,y);
126     }
127     dep[1] = 1;
128     dfs(1);
129     dfs2(1,1);
130     yuchu(1,tot,1);
131     rep(i,2,n){
132         add(shun[i-1],shun[i]);
133     }
134     rep(i,1,n) shun[w[i]] = i;
135     push(1);
136     rep(i,1,n){
137         printf("%d\n", w[i]);
138     }
139     return 0;
140 }

 

3631: [JLOI2014]松鼠的新家

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 991  Solved: 489
[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

posted on 2015-12-28 14:18  83131  阅读(185)  评论(0编辑  收藏  举报

导航