이름
효과에 따라
점의 무리가 있으며, 각각의 점은 무게가 \ (C_I \)를 .
각각의 삽입 측 \ ((U, V) \) \ (U \) 와 \ (1 \) 통신 \ (V \) 와 \ (1 \)는 연통되지 않는다. 마지막으로, 나무의 형성을 보장합니다.
심문 각각 삽입 \ (1 \)은 하기 (U \) \ 역방향 경로 페어 번호. 그런 다음 \ (1 \)를 하는 \ (U \) 경로에있는 모든 노드가 값으로 설정되어 오른쪽 \ (C_V \) .
역사에 대한 고찰
이것은 어떤 데이터 구조임을 알 것을 ......
하지만, 단지 오랜 시간 동안 어떻게 해야할지 ......하지 않습니다
그래서 그는 직접 폭력을 이겼다. 폭력 점프 \ (FA \) 역 펜윅 나무의 숫자를 사용하여 계산.
나중에 약간의 시간, 그래서 명소 \ (C_I의 \의 LEQ 2 \) 데이터입니다.
소위 분할 트리 플러스 가닥 세그먼트 트리가 유지됩니다. 각 트리 라인 유지 보수 간격이 크기입니다 \ (3 \) 배럴과 답변, 합병의 시간 간격은 양쪽 플러스 정답 왼쪽이 오른쪽에있는 수보다 큰 것입니다.
식사를 서둘러 연주 후 ...이 이전되지 않은
나중에이 나무는 ... 분할 내 원래의 폭력을 포함 chain'd 구분되지 않는 것을 발견 폭력입니다 ...... 먹을 수있는 \ (C_I의 \의 LEQ 2 \) 데이터 ......
정답
나는 긍정적 인 솔루션은 또한 충격을 볼 때 ......
마음으로 화면 시뮬레이션 작업에서 찾아보세요.
그런 다음에 시도 \ (LCT \) 접촉을 수립 할 수 있습니다.
그래서 우리는이 과정을 운영 것을 발견 \ (LCT는 \) 눈에 띄는 흡사!
각 (스플레이 \) \는 , 체인의 동일한 중량을 유지하는 시간에 상당하는 수정 (\ 액세스 \) ......까지
그 선조 경로 모두가 동일한 무게가된다.
우리는 또한 알고 \ (LCT \) 시간 복잡도가 동등하게 공유 (\ LG 전자 n 개의 \)가 \ 입니다.하지만 검증되지.
그래서 우리는 등장 세그먼트에 같은 색의 수를 이해할 수있는 \ (O (n \의 LG 전자 N을 ) \) 수준.
펜윅 나무에 의해 물었을 때 유지한다. 아날로그 \ (액세스 \) 그것에 과정.
그래서 질문은 AC 매우 쉽습니다. 그리고없이 완전하게이 문제 때문에 \ (mroot의 \) 작동, 그래서 플립하지 않는 ......
\ (LCT \) 짧은 체인 ...... 나무가 거의 분할한다
코드
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
int n;
int c[N],maxc;
int *p[N];
inline bool cmpp(int *x,int *y){
return *x<*y;
}
int t[N];
#define lowbit(x) ((x)&(-(x)))
inline void add(int x,int c){
for (;x<=maxc;x+=lowbit(x))
t[x]+=c;
}
inline int query(int x){
int res=0;
for (;x;x-=lowbit(x))
res+=t[x];
return res;
}
inline void clear(int x){
for (;x<=maxc && t[x];x+=lowbit(x))
t[x]=0;
}
struct Node{
Node *fa,*c[2];
int is_root;
int siz;
inline void update(){siz=c[0]->siz+c[1]->siz+1;}
inline bool getson(){return fa->c[0]!=this;}
inline void rotate(){
Node *y=fa,*z=y->fa;
if (y->is_root){
is_root=y->is_root;
y->is_root=0;
}
else
z->c[y->getson()]=this;
int k=getson();
fa=z;
y->c[k]=c[k^1];
c[k^1]->fa=y;
c[k^1]=y;
y->fa=this;
siz=y->siz,y->update();
}
inline void splay(){
while (!is_root){
if (!fa->is_root){
if (getson()!=fa->getson())
rotate();
else
fa->rotate();
}
rotate();
}
}
} d[N],*null;
int main(){
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;++i)
scanf("%d",&c[i]),p[i]=&c[i];
sort(p+1,p+n+1,cmpp);
for (int i=1,last=-1;i<=n;++i){
if (*p[i]!=last){
maxc++;
last=*p[i];
}
*p[i]=maxc;
}
null=d;
*null={null,null,null,0,0};
for (int i=1;i<=n;++i)
d[i]={null,null,null,c[i],1};
for (int i=1;i<n;++i){
int u,v;
scanf("%d%d",&u,&v);
Node *x,*y;
long long ans=0;
for (x=&d[u];x!=null;x=x->fa){
x->splay();
ans+=(long long)query(x->is_root-1)*(x->c[0]->siz+1);
add(x->is_root,x->c[0]->siz+1);
}
printf("%lld\n",ans);
d[v].fa=&d[u];
for (x=&d[v],y=null;x!=null;y=x,x=x->fa){
x->splay();
clear(x->is_root);
x->c[1]->is_root=x->is_root;
x->c[1]=y;
y->is_root=0;
x->update();
}
y->is_root=c[v];
}
return 0;
}
역사에 대한 고찰
복잡성을 분석 할 때, 당신은 배운 자신의 데이터 구조를 결합하려고 할 수 있습니다 ......