[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
solution:
非常裸地一个树链剖分
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 #define N 300005 7 int read() { 8 int s=0,f=1; 9 char ch=getchar(); 10 while(ch>'9'||ch<'0') { 11 if(ch=='-') { 12 f=-1; 13 } 14 ch=getchar(); 15 } 16 while(ch>='0'&&ch<='9') { 17 s=(s<<1)+(s<<3)+(ch^48); 18 ch=getchar(); 19 } 20 return s*f; 21 } 22 int n,a[N],r[N],tot,deep[N],fa[N],size[N],son[N]; 23 int tree[N*4],lazy[N*4],top[N],first[N],cnt,pos[N]; 24 struct edge { 25 int to,next; 26 } c[N<<1]; 27 void add(int x,int y) { 28 c[tot]=(edge) { 29 y,r[x] 30 }; 31 r[x]=tot++; 32 } 33 void dfs1(int x) { 34 size[x]=1; 35 son[x]=0; 36 for(int i=r[x]; ~i; i=c[i].next) { 37 if(fa[x]!=c[i].to) { 38 fa[c[i].to]=x; 39 deep[c[i].to]=deep[x]+1; 40 dfs1(c[i].to); 41 size[x]+=size[c[i].to]; 42 if(size[son[x]]<size[c[i].to]) { 43 son[x]=c[i].to; 44 } 45 } 46 } 47 } 48 void dfs2(int u,int v) { 49 top[u]=v; 50 first[u]=++cnt; 51 pos[cnt]=u; 52 if(son[u]) { 53 dfs2(son[u],v); 54 } 55 for(int i=r[u]; ~i; i=c[i].next) { 56 if(c[i].to!=fa[u]&&c[i].to!=son[u]) { 57 dfs2(c[i].to,c[i].to); 58 } 59 } 60 } 61 void pushup(int rt) { 62 tree[rt]=tree[rt<<1]+tree[rt<<1|1]; 63 } 64 void pushdown(int rt,int len) { 65 if(lazy[rt]) { 66 lazy[rt<<1]+=lazy[rt]; 67 lazy[rt<<1|1]+=lazy[rt]; 68 tree[rt<<1]+=lazy[rt]; 69 tree[rt<<1|1]+=lazy[rt]; 70 lazy[rt]=0; 71 } 72 } 73 void build(int i,int l,int r) { 74 lazy[i]=0; 75 if(l==r) { 76 tree[i]=0; 77 return ; 78 } 79 int mid=l+r>>1; 80 build(i<<1,l,mid); 81 build(i<<1|1,mid+1,r); 82 pushup(i); 83 } 84 void change(int l,int r,int val,int i,int L,int R) { 85 if(l<=L&&R<=r) { 86 lazy[i]+=val; 87 tree[i]+=val; 88 return ; 89 } 90 pushdown(i,R-L+1); 91 int mid=L+R>>1; 92 if(l<=mid) { 93 change(l,r,val,i<<1,L,mid); 94 } 95 if(r>mid) { 96 change(l,r,val,i<<1|1,mid+1,R); 97 } 98 pushup(i); 99 } 100 void Change(int x,int y,int val,int pd) { 101 int ji=x,kk=y; 102 int fx=top[x],fy=top[y]; 103 while(fx!=fy) { 104 if(deep[fx]<deep[fy]) { 105 swap(x,y); 106 swap(fx,fy); 107 } 108 change(first[fx],first[x],val,1,1,n); 109 x=fa[fx]; 110 fx=top[x]; 111 } 112 if(deep[x]>deep[y]) { 113 swap(x,y); 114 } 115 change(first[x],first[y],val,1,1,n); 116 if(pd>1){ 117 change(first[ji],first[ji],-val,1,1,n); 118 } 119 if(pd==n-1){ 120 change(first[kk],first[kk],-val,1,1,n); 121 } 122 } 123 int query(int pos,int i,int L,int R) { 124 if(L==R&&pos==L) { 125 return tree[i]; 126 } 127 pushdown(i,R-L+1); 128 int mid=L+R>>1; 129 if(pos<=mid) { 130 return query(pos,i<<1,L,mid); 131 } else { 132 return query(pos,i<<1|1,mid+1,R); 133 } 134 } 135 int main() { 136 memset(r,-1,sizeof(r)); 137 n=read(); 138 for(int i=1; i<=n; ++i) { 139 a[i]=read(); 140 } 141 for(int x,y,i=1; i<n; ++i) { 142 x=read(),y=read(); 143 add(x,y); 144 add(y,x); 145 } 146 dfs1(1); 147 dfs2(1,-1); 148 build(1,1,n); 149 for(int i=1; i<n; ++i) { 150 Change(a[i],a[i+1],1,i); 151 } 152 for(int i=1; i<=n; ++i) { 153 int ans=query(first[i],1,1,n); 154 if(i<n){ 155 printf("%d\n",ans); 156 }else{ 157 printf("%d",ans); 158 } 159 } 160 return 0; 161 }