[CF1172E]Nauuo and ODT:Link-Cut Tree

analysis

lxl major cancer.

Thank Ouuan and so such a good game CNOIER provided.

Here is the official solution to a problem to repeat it again, can go directly to the official Solution: Point me .

The problem is transformed into consideration for each color to determine the path node without this color how many, the answer to this question is:

\ [\ Sum_ {i = 1} ^ {n} (n ^ 2 \ sum_ {G} siz_ {G} ^ 2) \]

Wherein \ (G '\) is not included in all color \ (I \) Maximum block communication node.

Depending on the color \ (i \) node to the white point, black point for the rest, we need to do now is to maintain a data structure that supports:

  1. Change the color of a node.

  2. The size of the square of all the black dots extremely interrogation block and communicating.

Consider using LCT, even if each black dot edge to his father's words, so great communication block real black spot is the communication block each communication block to get rid of the root, so we can use the skills tree LCT child maintenance information maintain.

Note that \ (link (x) \) and \ (cut (x) \) implementation of a function. (Herein with reference to the standard process)

Time complexity is \ (O ((n-m +) \ n-log) \) .

Code

#include <bits/stdc++.h>

#define rin(i,a,b) for(int i=(a);i<=(b);++i)
#define irin(i,a,b) for(int i=(a);i>=(b);--i)
#define trav(i,a) for(int i=head[a];i;i=e[i].nxt)
#define Size(a) (int)a.size()
#define pb push_back
#define mkpr std::make_pair
#define fi first
#define se second
#define lowbit(a) ((a)&(-(a)))
#define sqr(a) ((a)*(a))
typedef long long LL;
typedef std::pair<int,int> pii;

using std::cerr;
using std::endl;

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

const int MAXN=400005;

int n,m,ecnt,head[MAXN];
int c[MAXN],fa[MAXN];
LL ans[MAXN],cur;
std::vector<pii> vec[MAXN];

struct Edge{
    int to,nxt;
}e[MAXN<<1];

inline void add_edge(int bg,int ed){
    ++ecnt;
    e[ecnt].to=ed;
    e[ecnt].nxt=head[bg];
    head[bg]=ecnt;
}

struct lct{
    int fa,ch[2];
    int siz;
    int isiz;
    LL ich2;
    bool tag;
}a[MAXN];

#define lc a[x].ch[0]
#define rc a[x].ch[1]

inline bool isroot(int x){
    return a[a[x].fa].ch[0]!=x&&a[a[x].fa].ch[1]!=x;
}

inline void pushr(int x){
    std::swap(lc,rc);
    a[x].tag^=1;
}

inline void pushdown(int x){
    if(!a[x].tag)return;
    if(lc)pushr(lc);
    if(rc)pushr(rc);
    a[x].tag=false;
}

inline void pushup(int x){  
    a[x].siz=a[lc].siz+a[rc].siz+1+a[x].isiz;   
}

inline void rotate(int x){
    int y=a[x].fa,z=a[y].fa,d=a[y].ch[1]==x,w=a[x].ch[d^1];
    if(!isroot(y))a[z].ch[a[z].ch[1]==y]=x;
    a[x].ch[d^1]=y;
    a[y].ch[d]=w;
    if(w)a[w].fa=y;
    a[y].fa=x;
    a[x].fa=z;
    pushup(y);
}

int top,sta[MAXN];

inline void splay(int x){
    int y=x,z=0;
    sta[top=1]=y;
    while(!isroot(y))sta[++top]=y=a[y].fa;
    while(top)pushdown(sta[top--]);
    while(!isroot(x)){
        y=a[x].fa,z=a[y].fa;
        if(!isroot(y)){
            if((a[z].ch[0]==y)==(a[y].ch[0]==x))rotate(y);
            else rotate(x);
        }
        rotate(x);
    }
    pushup(x);
}

inline void access(int x){
    for(int y=0;x;x=a[y=x].fa){
        splay(x);
        a[x].isiz+=a[rc].siz;
        a[x].ich2+=sqr(1ll*a[rc].siz);
        rc=y;
        a[x].isiz-=a[rc].siz;
        a[x].ich2-=sqr(1ll*a[rc].siz);
        pushup(x);
    }
}

inline void makeroot(int x){
    access(x);
    splay(x);
    pushr(x);
}

inline int findroot(int x){
    access(x);
    splay(x);
    while(pushdown(x),lc)x=lc;
    splay(x);
    return x;
}

inline void split(int x,int y){
    makeroot(x);
    access(y);
    splay(y);
}

inline void link(int x,int y){
    split(x,y);
    a[x].fa=y;
    a[y].isiz+=a[x].siz;
    a[y].ich2+=sqr(1ll*a[x].siz);
    pushup(y);
}

inline void cut(int x,int y){
    split(x,y);
    a[y].ch[0]=0;
    a[x].fa=0;
    pushup(y);
}

inline void link(int x){
    int y=fa[x];
    access(x);
    splay(x);
    cur-=a[x].ich2+sqr(1ll*a[rc].siz);
    int z=findroot(y);
    access(y);
    splay(z);
    cur-=sqr(1ll*a[a[z].ch[1]].siz);
    splay(y);
    a[x].fa=y;
    a[y].isiz+=a[x].siz;
    a[y].ich2+=sqr(1ll*a[x].siz);
    pushup(y);
    access(x);
    splay(z);
    cur+=sqr(1ll*a[a[z].ch[1]].siz);
}

inline void cut(int x){
    int y=fa[x];
    access(x);
    cur+=a[x].ich2;
    int z=findroot(y);
    access(x);
    splay(z);
    cur-=sqr(1ll*a[a[z].ch[1]].siz);
    splay(x);
    a[lc].fa=0;
    lc=0;
    pushup(x);
    access(y);
    splay(z);
    cur+=sqr(1ll*a[a[z].ch[1]].siz);
}

#undef lc
#undef rc

void dfs(int x,int pre){
    fa[x]=pre;
    trav(i,x){
        int ver=e[i].to;
        if(ver==pre)continue;
        dfs(ver,x);
    }
    a[x].fa=pre;
    a[pre].isiz+=a[x].siz;
    a[pre].ich2+=sqr(1ll*a[x].siz);
    pushup(pre);
}

int main(){
    n=read(),m=read();
    rin(i,1,n){
        c[i]=read();
        vec[c[i]].pb(mkpr(i,0));
    }
    rin(i,2,n){
        int u=read(),v=read();
        add_edge(u,v);
        add_edge(v,u);
    }
    rin(i,1,n+1)a[i].siz=1;
    dfs(1,n+1);
    rin(i,1,m){
        int x=read(),y=read();
        if(c[x]==y)continue;
        vec[c[x]].pb(mkpr(-x,i));
        c[x]=y;
        vec[c[x]].pb(mkpr(x,i));
    }
    cur=sqr(1ll*n);
    rin(i,1,n){
//      cerr<<"=========="<<i<<"=========="<<endl;
        rin(j,0,Size(vec[i])-1){
            int x=vec[i][j].fi;
            if(x>0)cut(x);
            else link(-x);
//          cerr<<x<<" "<<cur<<endl;
            ans[vec[i][j].se]+=sqr(1ll*n)-cur;
            ans[j==Size(vec[i])-1?m+1:vec[i][j+1].se]-=sqr(1ll*n)-cur;
        }
        irin(j,Size(vec[i])-1,0){
            int x=vec[i][j].fi;
            if(x>0)link(x);
            else cut(-x);
        }
    }
    rin(i,1,m)ans[i]+=ans[i-1];
    rin(i,0,m)printf("%lld\n",ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/ErkkiErkko/p/10994280.html