Codeforces 482E ELCA (LCT)

Topic Link

http://codeforces.com/contest/482/problem/E

answer

T2 T3 IQ title LCT big problem, I will not be a = =
CF it seems to be the standard calculation block? Anyway, now we are popular on the use of LCT LCT good.

Operators push the first two equations desirable, readily available answer is \ (\ sum_u A [U] (SZ [U] ^ 2- \ sum_ {V \ in Son [U]} SZ [V] ^ 2) \) ( \ (sz \) as a sub-tree size), so that things equal to the summation of \ (f [u] \)
and if to a \ (u \) was added a new one son \ (v \) , add after sub-tree size \ (sz [v] \) , then add the answer is \ (a [u] sz [
v] (sz [u] -sz [v]) \) then we want to support father change, this dynamic maintenance thing

Mang is on the back of a LCT.
This can only see the code, explain the meaning of code variables
for a Splay structure \ (U \) :
\ (ANS \) : subtree this point Splay in all points \ (f \) sum. Splay root of the \ (ans \) answer is required.
\ (sz01 \) : The point of all virtual sub-tree and the size of the add itself \ (1 \) . ( \ (Sz \) is the original tree neutron tree size)
\ (SZ02 \) : The point itself is the size of the squares of all virtual sub-tree and does not include itself.
\ (ANS0 \) : This point in itself all the imaginary son \ (ans \) sum.
\ (SZ11 \) : The point size of all real and imaginary son and his son's.
\ (SUM \) : The point of all real son \ (v \) is \ (sz01 [v] \ times a [v] \) sum.
These variables may seem incredible, we look at how to maintain.
First, all variables (that is, the name of Li Dai three 0's) son of imaginary sum in access processing, pushup time without treatment.
Now consider the pushup that function, the first two lines dealing\ (sz11 \) and \ (SUM \) , according to the definition of this request on the line, there is no much to say.
After four lines is the key - \ (ANS \) updates.

We \ (ans [u] \) divided into four parts count. (Optional two points \ (X \) and \ (Y \) find \ (a [lca (x, y)] \) and)
a first part: two points are selected in the \ (U \) ancestor ( within splay left subtree), or all at the right child within splay tree, or all at the \ (u \) inside with a virtual sub-tree.

spl[u].ans = spl[ls].ans+spl[u].ans0+spl[rs].ans;

Part II: In two tap \ (U \) of the two different virtual sub-tree.

spl[u].ans += (spl[u].sz01*spl[u].sz01-spl[u].sz02)*a[u];

One of the two points selected in the third part: \ (U \) in the virtual subtree, another tap in \ (U \) in the splay right subtree. Such LCA must be \ (U \) .

spl[u].ans += 2ll*spl[u].sz01*spl[rs].sz11*a[u];

One of the two selected points in: Part IV \ (U \) within ancestor (splay left subtree) or a virtual sub-tree, in other selected \ (U \) all points within the whole sub-tree and subtree splay virtual sub-tree removed \ (\ u) section above (in the splay left sub-tree and its virtual sub-tree), that is, \ (u \) and below (splay right child within the tree) and all points within the virtual sub-tree.

spl[u].ans += 2ll*spl[ls].sum*(spl[u].sz11-spl[ls].sz11);

So it is done. (The fourth part is a bit complicated)

Finally, this question worship out of the examination room cut new junior giant guy
zjr nb!

Code

#include<cstdio>
#include<cstdlib>
#include<iostream>
#define llong long long
using namespace std;
 
void read(int &x)
{
    int f=1;x=0;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}
    x*=f;
}
 
const int N = 1e5;
struct SplayNode
{
    int son[2],fa; llong sz01,sz11,sz02,sum,ans0,ans;
} spl[N+3];
int fa[N+3];
llong a[N+3];
int n,q;
 
bool isroot(int u) {return spl[spl[u].fa].son[0]!=u && spl[spl[u].fa].son[1]!=u;}
 
void pushup(int u)
{
    int ls = spl[u].son[0],rs = spl[u].son[1];
    spl[u].sz11 = spl[ls].sz11+spl[u].sz01+spl[rs].sz11;
    spl[u].sum = spl[ls].sum+spl[rs].sum+spl[u].sz01*a[u];
    spl[u].ans = spl[ls].ans+spl[u].ans0+spl[rs].ans;
    spl[u].ans += (spl[u].sz01*spl[u].sz01-spl[u].sz02)*a[u];
    spl[u].ans += 2ll*spl[u].sz01*spl[rs].sz11*a[u];
    spl[u].ans += 2ll*spl[ls].sum*(spl[u].sz11-spl[ls].sz11);
}
 
void rotate(int u)
{
    int x = spl[u].fa,y = spl[x].fa;
    spl[u].fa = y;
    if(!isroot(x)) {spl[y].son[x==spl[y].son[1]] = u;}
    int dir = u==spl[x].son[0];
    spl[x].son[dir^1] = spl[u].son[dir];
    if(spl[u].son[dir]) {spl[spl[u].son[dir]].fa = x;}
    spl[u].son[dir] = x; spl[x].fa = u;
    pushup(x); pushup(u);
}
 
void splaynode(int u)
{
    while(!isroot(u))
    {
        int x = spl[u].fa,y = spl[x].fa;
        if(!isroot(x)) {x==spl[y].son[1] ^ u==spl[x].son[1] ? rotate(u) : rotate(x);}
        rotate(u);
    }
    pushup(u);
}
 
void access(int u)
{
    for(int i=0; u; i=u,u=spl[u].fa)
    {
        splaynode(u);
        int ls = spl[u].son[0],rs = spl[u].son[1];
        spl[u].sz01 += spl[rs].sz11;
        spl[u].sz02 += spl[rs].sz11*spl[rs].sz11;
        spl[u].ans0 += spl[rs].ans; //not ans0
        rs = spl[u].son[1] = i;
        spl[u].sz01 -= spl[rs].sz11;
        spl[u].sz02 -= spl[rs].sz11*spl[rs].sz11;
        spl[u].ans0 -= spl[rs].ans;
        pushup(u);
    }
}
 
void link(int u,int v)
{
    access(v); splaynode(v);
    access(u); splaynode(u); //in order to pushup
    spl[u].sz01 += spl[v].sz11;
    spl[u].sz02 += spl[v].sz11*spl[v].sz11;
    spl[u].ans0 += spl[v].ans;
    spl[v].fa = u;
    pushup(u);
}
 
void cut(int u,int v)
{
    access(u); splaynode(u);
    splaynode(v); //v is in the virtual subtree of u
    spl[u].sz01 -= spl[v].sz11;
    spl[u].sz02 -= spl[v].sz11*spl[v].sz11;
    spl[u].ans0 -= spl[v].ans;
    spl[v].fa = 0;
    pushup(u);
}
 
bool isanc(int u,int v) //if u is ancestor of v
{
    access(v); splaynode(v);
    splaynode(u);
    if(!isroot(v)) return true;
    return false;
}
 
void printans(llong x)
{
    double ans = (double)x/(double)n/(double)n;
    printf("%.12lf\n",ans);
}
 
int main()
{
    scanf("%d",&n);
    for(int i=2; i<=n; i++) scanf("%d",&fa[i]);
    for(int i=1; i<=n; i++) scanf("%I64d",&a[i]);
    for(int i=1; i<=n; i++) spl[i].sz11 = spl[i].sz01 = 1ll,spl[i].ans = spl[i].sum = a[i];
    for(int i=2; i<=n; i++)
    {
        link(fa[i],i);
    }
    access(1); splaynode(1);
    printans(spl[1].ans);
    scanf("%d",&q);
    for(int i=1; i<=q; i++)
    {
        char opt[5]; scanf("%s",opt+1);
        if(opt[1]=='P')
        {
            int x,y; scanf("%d%d",&x,&y);
            if(isanc(x,y)) {swap(x,y);}
            cut(fa[x],x);
            fa[x] = y;
            link(fa[x],x);
            access(1); splaynode(1);
            printans(spl[1].ans);
        }
        else if(opt[1]=='V')
        {
            int x; llong y; scanf("%d%I64d",&x,&y);
            access(x); splaynode(x);
            a[x] = y;
            pushup(x);
            printans(spl[x].ans);
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/suncongbo/p/11330695.html