LOJ2434. "ZJOI2018" history [LCT]

SIZE

Thinking

At first glance seems to be no idea, try to set up a DP: Let \ (dp_x \) represents only consider \ (x \) maximum answer subtree can get.

Found that only when the merger \ (x \) at this point it is possible to make new contributions, while the time to make new contributions to the two countries must be different from the sub-tree of war.

So practice suddenly clear up: For each point \ (the X-\) , remember \ (s \) indicates how many times the rise in the sub-tree, \ (the p-\) indicates how many times the rise of the largest sub-tree (also possible that \ ( x \) himself), then its contribution to the answer is
\ [\ min (s-1,2
(sp)) \] Why? In fact, a process that consumes the largest sub-tree with the other sub-tree.

Consider what happens when modified. We affects \ (x \) to the root of a chain, chain above \ (s \) plus 1, and \ (p \) is not yet known.

We make \ (. 1-S> 2 (SP) \) , to give \ (2P> +. 1 S \) .

At this time, we make to meet the conditions of his son as his son heavy, heavy son found only one, and if they are on the son and heavy piece of chain, so heavy son will not change, the answer is the same. Only this chain across a light side when will it be possible to change the answer.

We also found a number of light points to the root of the strip is \ (O (\ log n) \) a.

So this is a dynamic change in the severity of side of things, for maintenance LCT.

Complexity does not know? Anyway, no more than \ (O (the n-\ log ^ the n-2) \) , and seems to run pretty fast.

Code

Note that accessthe operation which has classified some of the details of the discussion, I missed the first 129 rows in the result tune 1h ......

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
    using namespace std;
    #define pii pair<int,int>
    #define fir first
    #define sec second
    #define MP make_pair
    #define rep(i,x,y) for (int i=(x);i<=(y);i++)
    #define drep(i,x,y) for (int i=(x);i>=(y);i--)
    #define go(x) for (int i=head[x];i;i=edge[i].nxt)
    #define templ template<typename T>
    #define sz 404004
    typedef long long ll;
    typedef double db;
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
    templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
    templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
    templ inline void read(T& t)
    {
        t=0;char f=0,ch=getchar();double d=0.1;
        while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
        if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
        t=(f?-t:t);
    }
    template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
    char __sr[1<<21],__z[20];int __C=-1,__zz=0;
    inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
    inline void print(register int x)
    {
        if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
        while(__z[++__zz]=x%10+48,x/=10);
        while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
    }
    void file()
    {
        #ifdef NTFOrz
        freopen("a.in","r",stdin);
        #endif
    }
    inline void chktime()
    {
        #ifndef ONLINE_JUDGE
        cout<<(clock()-t)/1000.0<<'\n';
        #endif
    }
    #ifdef mod
    ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
    ll inv(ll x){return ksm(x,mod-2);}
    #else
    ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
    #endif
//  inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;

int n,m;
ll a[sz];
struct hh{int t,nxt;}edge[sz<<1];
int head[sz],ecnt;
void make_edge(int f,int t)
{
    edge[++ecnt]=(hh){t,head[f]};
    head[f]=ecnt;
    edge[++ecnt]=(hh){f,head[t]};
    head[t]=ecnt;
}

int fa[sz],ch[sz][2];
ll s[sz],size[sz];
#define ls ch[x][0]
#define rs ch[x][1]
void pushup(int x){size[x]=size[ls]+size[rs]+s[x]+a[x];}
int get(int x){return ch[fa[x]][1]==x;}
int nroot(int x){return ch[fa[x]][0]==x||ch[fa[x]][1]==x;}
void rotate(int x)
{
    int y=fa[x],z=fa[y],k=get(x),w=ch[x][!k];
    if (nroot(y)) ch[z][get(y)]=x;ch[x][!k]=y;ch[y][k]=w;
    if (w) fa[w]=y;fa[y]=x;fa[x]=z;
    pushup(y),pushup(x);
}
void splay(int x){for (int y;y=fa[x],nroot(x);rotate(x)) if (nroot(y)) rotate(get(x)==get(y)?y:x);}

ll ans;

int type[sz];
#define v edge[i].t
void dfs(int x,int f)
{
    ll mx=a[x];int son=x;
    go(x) if (v!=f)
    {
        dfs(v,x);
        size[x]+=size[v];
        if (chkmax(mx,size[v])) son=v;
    }
    if (mx*2<=size[x]+a[x]+1) type[x]=0;
    else if (son==x) type[x]=1;
    else type[x]=2,rs=son;
    s[x]=size[x]-size[rs];size[x]+=a[x];fa[x]=f;
    if (type[x]) ans+=2*(size[x]-mx);
    else ans+=size[x]-1;
}
#undef v

int main()
{
    file();
    read(n,m);
    rep(i,1,n) read(a[i]);
    int x,y;
    rep(i,1,n-1) read(x,y),make_edge(x,y);
    dfs(1,0);
    printf("%lld\n",ans);
    while (m--)
    {
        int p;ll w;read(p,w);
        for (int x=p;x;x=fa[x]) splay(x),s[x]+=w,size[x]+=w;
        s[p]-=w;a[p]+=w;
        for (int x=p,y=0;x;x=fa[y=x])
        {
            splay(x);
            ll S=size[x]-size[ls];
            if (!type[x]) ans-=S-w-1;
            else if (type[x]==1&&x!=p) ans-=2ll*(S-w-a[x]);
            else if (type[x]==1&&x==p) ans-=2ll*(S-a[x]);
            else ans-=2ll*(S-w-size[rs]);
            if (size[y]*2>S+1) s[x]+=size[rs]-size[y],rs=y,pushup(x);
            if (size[rs]*2>S+1) ans+=2ll*(S-size[rs]),type[x]=2;
            else if (a[x]*2>S+1) ans+=2ll*(S-a[x]),s[x]+=size[rs],type[x]=1,rs=0,pushup(x);
            else ans+=S-1,s[x]+=size[rs],rs=0,pushup(x),type[x]=0;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/p-b-p-b/p/11391063.html