[JZOJ6257] [8.9] 도로 시뮬레이션 지방 선거

이름

효과에 따라

점의 무리가 있으며, 각각의 점은 무게가 \ (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;
}

역사에 대한 고찰

복잡성을 분석 할 때, 당신은 배운 자신의 데이터 구조를 결합하려고 할 수 있습니다 ......

추천

출처www.cnblogs.com/jz-597/p/11329667.html