BZOJ3631 [JLOI2014] 松鼠的新家

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3631

Description

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

Input

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

Output

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

以前第一次看到认为是倍增,现在一眼扫过去裸链剖……我还是Too young, too simple, sometimes naive. 

这道题要求对每一个节点都输出答案,实测对整棵树自上而下递归一次记录每个节点的答案,比用普通线段树通用的询问方法能快300ms左右。

对于某个节点,如果它不是起点则要将答案减1(因为有重复计算)。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #define rep(i,l,r) for(int i=l; i<=r; i++)
  6 #define clr(x,y) memset(x,y,sizeof(x))
  7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
  8 using namespace std;
  9 const int maxn = 300010;
 10 struct Edge{
 11     Edge *pre;
 12     int to;
 13 }edge[maxn<<1];
 14 Edge *last[maxn],*pt;
 15 struct node{
 16     int l,r,v,t;
 17 }t[maxn<<2];
 18 int n,x,y,segnum=0,a[maxn],depth[maxn],fa[maxn],size[maxn],pos[maxn],belong[maxn],ans[maxn];
 19 bool vis[maxn];
 20 inline int read(){
 21     int ans = 0, f = 1;
 22     char c = getchar();
 23     while (!isdigit(c)){
 24         if (c == '-') f = -1;
 25         c = getchar();
 26     }
 27     while (isdigit(c)){
 28         ans = ans * 10 + c - '0';
 29         c = getchar();
 30     }
 31     return ans * f;
 32 }
 33 inline void addedge(int x,int y){
 34     pt->pre = last[x]; pt->to = y; last[x] = pt++;
 35 }
 36 void dfs1(int x){
 37     vis[x] = 1; size[x] = 1;
 38     travel(x){
 39         if (vis[p->to]) continue;
 40         depth[p->to] = depth[x] + 1;
 41         fa[p->to] = x;
 42         dfs1(p->to);
 43         size[x] += size[p->to];
 44     }
 45 }
 46 void dfs2(int x,int chain){
 47     int k = 0; pos[x] = ++segnum; belong[x] = chain;
 48     travel(x){
 49         if (depth[p->to] == depth[x] + 1 && size[p->to] > size[k])
 50         k = p->to;
 51     }
 52     if (!k) return;
 53     dfs2(k,chain);
 54     travel(x){
 55         if (p->to != k && depth[p->to] > depth[x])
 56         dfs2(p->to,p->to);
 57     }
 58 }
 59 inline void pushdown(int w){
 60     if ((!t[w].t) || t[w].l == t[w].r) return;
 61     t[w<<1].t += t[w].t; t[w<<1|1].t += t[w].t;
 62     t[w<<1].v += (t[w<<1].r - t[w<<1].l + 1) * t[w].t;
 63     t[w<<1|1].v += (t[w<<1|1].r - t[w<<1|1].l + 1) * t[w].t;
 64     t[w].t = 0;
 65 }
 66 inline void maintain(int w){
 67     t[w].v = t[w<<1].v + t[w<<1|1].v;
 68 }
 69 void build(int u,int v,int w){
 70     t[w].l = u; t[w].r = v; t[w].v = t[w].t = 0;
 71     if (u == v) return;
 72     int mid = (u + v) >> 1;
 73     build(u,mid,w<<1); build(mid+1,v,w<<1|1);
 74 }
 75 void change(int u,int v,int w){
 76     pushdown(w);
 77     if (u == t[w].l && v == t[w].r){
 78         t[w].v += v - u + 1;
 79         t[w].t += 1;
 80         return;
 81     }
 82     int mid = (t[w].l + t[w].r) >> 1;
 83     if (v <= mid) change(u,v,w<<1);
 84     else if (u > mid) change(u,v,w<<1|1);
 85     else{
 86         change(u,mid,w<<1);
 87         change(mid+1,v,w<<1|1);
 88     }
 89     maintain(w);
 90 }
 91 void getans(int u,int v,int w){
 92     pushdown(w);
 93     if (u == v){
 94         ans[u] = t[w].v;
 95         return;
 96     }
 97     int mid = (u + v) >> 1;
 98     getans(u,mid,w<<1); getans(mid+1,v,w<<1|1);
 99 }
100 void modify(int x,int y){
101     while (belong[x] != belong[y]){
102         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
103         change(pos[belong[x]],pos[x],1);
104         x = fa[belong[x]];
105     }
106     if (depth[x] < depth[y]) swap(x,y);
107     change(pos[y],pos[x],1);
108 }
109 int main(){
110     n = read(); rep(i,1,n) a[i] = read();
111     clr(last,0); pt = edge;
112     rep(i,1,n-1){
113         x = read(); y = read(); addedge(x,y); addedge(y,x);
114     }
115     clr(vis,0); depth[1] = 1; dfs1(1); dfs2(1,1);
116     build(1,n,1);
117     rep(i,2,n) modify(a[i],a[i-1]);
118     getans(1,n,1);
119     rep(i,1,n){
120         printf("%d
",i == a[1] ? ans[pos[i]] : ans[pos[i]] - 1);
121     }
122     return 0;
123 }
View Code
原文地址:https://www.cnblogs.com/jimzeng/p/bzoj3631.html