用 LCT 维护颜色相同连通块,然后在线段树上查一下逆序对个数就可以了.
code:
#include <cstdio> #include <algorithm> #include <cstring> #include <string> #define N 100005 #define ll long long using namespace std; namespace IO { void setIO(string s) { string in=s+".in"; string out=s+".out"; freopen(in.c_str(),"r",stdin); // freopen(out.c_str(),"w",stdout); } }; ll ans; int n,val[N],A[N]; namespace seg { int lazy[N<<2],sum[N<<2]; void mark(int now) { sum[now]=0,lazy[now]=1; } void pushdown(int now) { if(lazy[now]) mark(now<<1),mark(now<<1|1),lazy[now]=0; } void update(int l,int r,int now,int p,int v) { if(l==r) { sum[now]+=v; return; } pushdown(now); int mid=(l+r)>>1; if(p<=mid) update(l,mid,now<<1,p,v); else update(mid+1,r,now<<1|1,p,v); sum[now]=sum[now<<1]+sum[now<<1|1]; } int query(int l,int r,int now,int L,int R) { if(L>R) return 0; if(l>=L&&r<=R) return sum[now]; pushdown(now); int re=0,mid=(l+r)>>1; if(L<=mid) re+=query(l,mid,now<<1,L,R); if(R>mid) re+=query(mid+1,r,now<<1|1,L,R); return re; } }; namespace LCT { #define lson s[x].ch[0] #define rson s[x].ch[1] struct node { int ch[2],rev,f,tag,size; }s[N]; int sta[N]; inline int get(int x) { return s[s[x].f].ch[1]==x; } inline int isr(int x) { return s[s[x].f].ch[0]!=x&&s[s[x].f].ch[1]!=x; } inline void pushup(int x) { s[x].size=s[lson].size+s[rson].size+1; } inline void mark(int x,int v) { s[x].tag=v; } inline void pushdown(int x) { if(lson) mark(lson,s[x].tag); if(rson) mark(rson,s[x].tag); } inline void rotate(int x) { int old=s[x].f,fold=s[old].f,which=get(x); if(!isr(old)) s[fold].ch[s[fold].ch[1]==old]=x; s[old].ch[which]=s[x].ch[which^1]; if(s[old].ch[which]) s[s[old].ch[which]].f=old; s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold; pushup(old),pushup(x); } inline void splay(int x) { int v=0,u=x,fa; for(sta[++v]=u;!isr(u);u=s[u].f) sta[++v]=s[u].f; for(;v;--v) pushdown(sta[v]); for(u=s[u].f;(fa=s[x].f)!=u;rotate(x)) if(s[fa].f!=u) rotate(get(fa)==get(x)?fa:x); } inline void Access(int x,int v) { for(int y=0;x;y=x,x=s[x].f) { splay(x),rson=0,pushup(x); ans+=(ll)s[x].size*seg::query(1,n,1,1,s[x].tag-1); seg::update(1,n,1,s[x].tag,s[x].size); rson=y,s[x].tag=v,pushup(x); } } inline void link(int x,int y) { s[y].f=x; } #undef lson #undef rson }; int main() { // IO::setIO("input"); int i,j; scanf("%d",&n); for(i=1;i<=n;++i) scanf("%d",&val[i]),A[i]=val[i]; sort(A+1,A+1+n); for(i=1;i<=n;++i) val[i]=lower_bound(A+1,A+1+n,val[i])-A,LCT::s[i].tag=val[i]; for(i=1;i<n;++i) { int x,y; scanf("%d%d",&x,&y); ans=0; seg::mark(1); LCT::Access(x,val[y]); LCT::link(x,y); printf("%lld ",ans); } return 0; }