題目傳送門:23333
十分考驗樹剖的本事
在網上看到幾個大神寫樹剖T掉了233333
主要是樹剖,剖完後把一條路上的點不停地打永久標記,不用向下推,查詢時直接把flag加起來就好了。
另外除了第一個點外其餘點都要減一,中間的點進入會拿一顆糖,出時也會計算一個,所以要減去。
最後一個房間的糖題目說了不用,所以也要減。
(雖說被這個坑了好久QAQ)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#define rep(j,k,l) for (int j=k;j<=l;j++)
#define N 300005
using namespace std;
struct _233{
int l,r,flag;
} tr[N*4];
int n,cnt,a[N],ne[N*2],to[N*2],st[N];
int as[N],size[N],son[N],deep[N],fa[N],top[N],dfn[N],id[N];
void add(int k,int l,int p){
to[p]=l;
ne[p]=st[k];
st[k]=p;
}
void dfs1(int rt,int dad){
size[rt]=1;
fa[rt]=dad;
deep[rt]=deep[dad]+1;
son[rt]=0;int _=0;
for (int i=st[rt];i!=0;i=ne[i])
if (to[i]!=dad){
dfs1(to[i],rt);
size[rt]+=size[to[i]];
if (size[to[i]]>_){
_=size[to[i]];
son[rt]=to[i];
}
}
}
void dfs2(int rt,bool qaz){
if (qaz) top[rt]=top[fa[rt]];
else top[rt]=rt;
dfn[++cnt]=rt;
id[rt]=cnt;
if (son[rt]!=0) dfs2(son[rt],1);
for (int i=st[rt];i!=0;i=ne[i])
if (to[i]!=fa[rt]&&to[i]!=son[rt])
dfs2(to[i],0);
}
void stree(int k,int l,int r){
if (l==r) return;
tr[k].l=++cnt;
tr[k].r=++cnt;
stree(tr[k].l,l,(l+r)/2);
stree(tr[k].r,(l+r)/2+1,r);
}
void change(int k,int l,int r,int o,int p){
if (o>r||p<l) return;
if (o<=l&&r<=p){
tr[k].flag+=1;
return;
}
change(tr[k].l,l,(l+r)/2,o,p);
change(tr[k].r,(l+r)/2+1,r,o,p);
return;
}
void work(int x,int y){
for (;top[x]!=top[y];x=fa[top[x]]){
if (deep[top[x]]<deep[top[y]]) swap(x,y);
change(1,1,n,id[top[x]],id[x]);
//printf("%d %d\n",top[x],x);
}
change(1,1,n,min(id[x],id[y]),max(id[x],id[y]));
//printf("%d %d\n",min(id[x],id[y]),max(id[x],id[y]));
//printf("\n");
}
void print(int k,int l,int r,int f){
if (l==r){
if (dfn[l]==a[1]) f++;
as[dfn[l]]=f+tr[k].flag;
return;
}
print(tr[k].l,l,(l+r)/2,f+tr[k].flag);
print(tr[k].r,(l+r)/2+1,r,f+tr[k].flag);
}
void tiaoshi(int k,int l,int r){
printf("%d %d %d\n",l,r,tr[k].flag);
if (l==r) return;
tiaoshi(tr[k].l,l,(l+r)/2);
tiaoshi(tr[k].r,(l+r)/2+1,r);
}
int main(){
scanf("%d",&n);
rep(i,1,n) scanf("%d",&a[i]);
rep(i,1,n-1){
int k,l;
scanf("%d%d",&k,&l);
add(k,l,2*i-1);
add(l,k,2*i);
}
dfs1(1,0);
dfs2(1,0);
cnt=1;
stree(1,1,n);
//for(int i=1;i<=5;i++) printf("%d\n",top[i]);
rep(i,2,n) work(a[i],a[i-1]);//tiaoshi(1,1,n),printf("\n");
print(1,1,n,0);
rep(i,1,n) printf("%d\n",as[i]-1);
system("pause");
}