[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
提示
2<= n <=300000
树链剖分裸题,全当复习了。
首先既然是在树上,那么两点之间的路径就是唯一的了,果断树剖,其实LCA也可以,不过时间复杂度貌似并不允许,所以放弃。
首先,可以明确的是,我们直接从a[1]点位出发一定是最优的,不知道Q某犇为啥会纠结这个,然后就是慢慢慢慢的树剖了,然后就是一两个坑点,首先,虽然每一次树剖都是从a[i]~a[i+1],但a[i]早在求a[i-1]~a[i]时算过了,所以当我们最后输出的时候一定要记得把a[2~n]的结果-1。为什么要把a[n]的结果也减一呢?读题,a[n]是餐厅,因此不必放糖,但这并不意味着来回经过不必放糖,所以在最后一起减掉就好了。
1 #include<iostream> 2 #include<cstdlib> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<map> 7 #include<queue> 8 #include<string> 9 #include<cmath> 10 # define N 300005 11 using namespace std; 12 int n; 13 int b[300005],a[300004]; 14 struct ro{ 15 int to; 16 int next; 17 }road[1000005]; 18 int zz; 19 void build(int x,int y){ 20 zz++; 21 road[zz].to=y; 22 road[zz].next=a[x]; 23 a[x]=zz; 24 } 25 int deep[N],fa[N],hson[N],size[N]; 26 void dfs(int x,int dep){ 27 deep[x]=dep; 28 size[x]=1; 29 for(int i=a[x];i>0;i=road[i].next) 30 { 31 int y=road[i].to; 32 if(fa[x]==y)continue; 33 fa[y]=x; 34 dfs(y,dep+1); 35 size[x]+=size[y]; 36 if(size[hson[x]]<size[y]) 37 hson[x]=y; 38 } 39 } 40 int zz2; 41 int f2[N],dl[N],dfn[N]; 42 void dfs2(int x,int top){ 43 f2[x]=top; 44 zz2++; 45 dl[zz2]=x; 46 dfn[x]=zz2; 47 if(hson[x]) dfs2(hson[x],top); 48 for(int i=a[x];i>0;i=road[i].next) 49 { 50 int y=road[i].to; 51 if(y==fa[x]||y==hson[x]) continue; 52 dfs2(y,y); 53 } 54 } 55 struct no{ 56 int sum; 57 int lazy; 58 int right,left; 59 int mid; 60 }node[4*N]; 61 void build(int left,int right,int x){ 62 node[x].left=left; 63 node[x].right=right; 64 if(left==right) 65 { 66 return; 67 } 68 int mid=(left+right)/2; 69 node[x].mid=mid; 70 build(left,mid,2*x); 71 build(mid+1,right,2*x+1); 72 } 73 void pushdown(int x){ 74 if(node[x].lazy) 75 { 76 node[2*x].lazy+=node[x].lazy; 77 node[2*x+1].lazy+=node[x].lazy; 78 node[x*2].sum+=node[x].lazy; 79 node[2*x+1].sum+=node[x].lazy; 80 node[x].lazy=0; 81 } 82 } 83 void add(int left,int right,int x){ 84 if(node[x].left==left&&node[x].right==right) 85 { 86 node[x].sum++; 87 node[x].lazy++; 88 return; 89 } 90 pushdown(x); 91 int mid=node[x].mid; 92 if(right<=mid) 93 { 94 add(left,right,2*x); 95 } 96 else if(mid<left) 97 { 98 add(left,right,2*x+1); 99 } 100 else 101 { 102 add(left,mid,2*x); 103 add(mid+1,right,2*x+1); 104 } 105 node[x].sum=node[x*2].sum+node[2*x+1].sum; 106 } 107 int get(int left,int right,int x) 108 { 109 if(node[x].left==node[x].right) 110 { 111 return node[x].sum; 112 } 113 pushdown(x); 114 int mid=node[x].mid; 115 if(left<=mid) 116 return get(left,right,2*x); 117 else 118 return get(left,right,2*x+1); 119 } 120 void change(int x,int y){ 121 122 int fx=f2[x],fy=f2[y]; 123 while(fx!=fy) 124 { 125 if(deep[fx]<deep[fy]) 126 { 127 swap(fx,fy); 128 swap(x,y); 129 } 130 add(dfn[fx],dfn[x],1); 131 x=fa[fx]; 132 fx=f2[x]; 133 } 134 135 if(deep[y]<deep[x]) swap(y,x); 136 if(dfn[x]<=dfn[y]) 137 add(dfn[x],dfn[y],1); 138 139 } 140 int main(){ 141 scanf("%d",&n); 142 for(int i=1;i<=n;i++) 143 scanf("%d",&b[i]); 144 for(int i=1;i<n;i++) 145 { 146 int x,y; 147 scanf("%d%d",&x,&y); 148 build(x,y); 149 build(y,x); 150 } 151 dfs(1,1); 152 dfs2(1,1); 153 build(1,n,1); 154 for(int i=2;i<=n;i++) 155 { 156 change(b[i-1],b[i]); 157 } 158 for(int i=1;i<=n;i++) 159 { 160 //cout<<endl; 161 int x=get(dfn[i],dfn[i],1); 162 if(i!=b[1]) 163 x--; 164 printf("%d ",x); 165 } 166 //while(1); 167 return 0; 168 }