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 MBSubmit: 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
1 4 5 3 2
1 2
2 4
2 3
4 5
Sample Output
1
2
1
2
1
2
1
2
1
HINT
2<= n <=300000
————————————————