Nauuo and ODT CF1172E

A practiced hand LCT title,
will ask offline, considered separately for each color
at least the number of paths we ask is that after a certain color once.
Consider inclusion and exclusion,
it is to use the total number of paths without subtracting the number of
markers that point color is white, the other black
times the size of the square is without communication black block.
We will all black spots even edge to his father, in fact, each communication block black top has a white spot, square and we maintain sub-tree, the white point each to the top of the statistics can answer.

/*
@Date    : 2019-08-14 08:07:13
@Author  : Adscn ([email protected])
@Link    : https://www.cnblogs.com/LLCSBlog
*/
#include<bits/stdc++.h>
using namespace std;
#define IL inline
#define RG register
#define gi getint()
#define gc getchar()
#define File(a) freopen(a".in","r",stdin);freopen(a".out","w",stdout)
IL int getint()
{
    RG int xi=0;
    RG char ch=gc;
    bool f=0;
    while(ch<'0'||ch>'9')ch=='-'?f=1:f,ch=gc;
    while(ch>='0'&&ch<='9')xi=(xi<<1)+(xi<<3)+ch-48,ch=gc;
    return f?-xi:xi;
}
template<typename T>
IL void pi(T k,char ch=0)
{
    if(k<0)k=-k,putchar('-');
    if(k>=10)pi(k/10,0);
    putchar(k%10+'0');
    if(ch)putchar(ch);
}
const int N=4e5+7;
int n,m;
struct edge{
    int v,nxt;
}e[N<<1];
int head[N],cnt;
inline void add(int u,int v){e[++cnt]=(edge){v,head[u]},head[u]=cnt;}
namespace LCT{
    #define ls(x) (c[x][0])
    #define rs(x) (c[x][1])
    #define s(x,k) (c[x][k])
    int val[N],f[N],siz[N],si[N];
    long long siz2[N],si2[N];//si 轻儿子
    int c[N][2];
    inline long long sqr(int x){return 1ll*x*x;}
    inline bool ws(int x,int p){return ls(p)^x;}
    inline bool nroot(int x){return ls(f[x])==x||rs(f[x])==x;}
    inline void pushup(int x){
        siz[x]=siz[ls(x)]+siz[rs(x)]+si[x]+1;
        siz2[x]=sqr(siz[ls(x)])+sqr(siz[rs(x)])+si2[x];
    }
    inline void rotate(int x)
    {
        int p=f[x],g=f[p];
        int t=ws(x,p),w=s(x,!t);
        if(nroot(p))s(g,ws(p,g))=x;s(x,!t)=p;s(p,t)=w;
        if(w)f[w]=p;f[p]=x;f[x]=g;
        pushup(p);
    }
    inline void Splay(int x){
        while(nroot(x)){
            int p=f[x],g=f[p];
            if(nroot(p))rotate(ws(x,p)^ws(p,g)?x:p);
            rotate(x);
        }
        pushup(x);
    }
    inline void access(int x){
        for(int y=0;x;x=f[y=x])
            Splay(x),si[x]+=siz[rs(x)]-siz[y],si2[x]+=sqr(siz[rs(x)])-sqr(siz[y]),rs(x)=y,pushup(x);
    }
    inline int findroot(int x){
        access(x),Splay(x);
        while(ls(x))x=ls(x);
        return Splay(x),x;
    }
    inline void link(int u,int v)
    {
        access(v),Splay(v);Splay(u);
        si[v]+=siz[u],si2[v]+=sqr(siz[u]);
        pushup(f[u]=v);
    }
    inline void cut(int u,int v)
    {
        access(v),Splay(v);Splay(u);
        si[v]-=siz[u],si2[v]-=sqr(siz[u]),f[u]=0;
        pushup(v);
    }
}
using namespace LCT;
int fa[N],col[N];
long long ans[N];
inline void dfs(int p){for(int i=head[p];~i;i=e[i].nxt)if(e[i].v^fa[p])fa[e[i].v]=p,dfs(e[i].v);}
struct operation{
    int tim,u,opt;
};
vector<operation>opt[N];
int main(void)
{
    #ifndef ONLINE_JUDGE
//  File("color");
    #endif
    memset(head,cnt=-1,sizeof head);
    n=gi,m=gi;
    for(int i=1;i<=n;++i)col[i]=gi;
    for(int i=1;i<n;++i)
    {
        int u=gi,v=gi;
        add(u,v),add(v,u);
    }
    dfs(1);fa[1]=n+1;
    fill(siz+1,siz+n+2,1);
    for(int i=1;i<=n;++i)link(i,fa[i]);
//  for(int i=1;i<=n;++i)cout<<fa[i]<<" ";
//  cout<<endl;
    for(int i=1;i<=n;++i)opt[col[i]].push_back((operation){0,i,0});
    for(int i=1;i<=m;++i)
    {
        int u=gi,x=gi;
        opt[col[u]].push_back((operation){i,u,1});
        opt[col[u]=x].push_back((operation){i,u,0});
    }
    for(int i=1;i<=n;++i)opt[col[i]].push_back((operation){m+1,i,1});
    for(int i=1;i<=n;++i)
        for(auto&& x:opt[i]){
            int t=x.tim,u=x.u,p=findroot(fa[u]);
            if(x.opt)
            {
                Splay(p),Splay(u);
                ans[t]+=siz2[p]+siz2[u];
                link(u,fa[u]);
                Splay(p),ans[t]-=siz2[p];
            }
            else
            {
                Splay(p),ans[t]+=siz2[p];
                cut(u,fa[u]);
                Splay(p),Splay(u),ans[t]-=siz2[p]+siz2[u];
            }
        }
    for(int i=1;i<=m;++i)ans[i]+=ans[i-1];
    for(int i=0;i<=m;++i)pi(ans[i],'\n');
    return 0;
}

Guess you like

Origin www.cnblogs.com/LLCSBlog/p/11355776.html