luogu 3676 small fresh data structure that

True small fresh ...

In fact, this problem positive solution is dynamic point divide and conquer, but considering the things that need to be vigorously derive a wave and then put on a fantasy strategy game township engage in law, so it was not as strong a wave of derivation, then no brain put a cross + segment tree tree wording ...

First, we consider not change root operations:

When there is no change root operation, provided the amount of change per modification $ \ Delta $, obviously only affect the contribution of each tree on a chain is modified, set $ s_ {i} $ $ I $ is represented by a root node weights and sub-tree, the contribution of each modification to produce the answer is:

$\sum_{i\in [p~root]}(s_{i}+\delta)^{2}-\sum_{i\in [p~root]}s_{i}^{2}$

Expand this expression, too:

$dep_{p}\delta^{2}+2\delta\sum_{i\in [p~root]}s_{i}$

In other words, we actually maintain that $ s_ {i} $, each modification only add to the answer to that expression

While maintaining $ s_ {i} $ + sectional tree may simply modify the segment tree section, inquiry interval calculated

Then consider the next question:

If you change the root of how to do?

We consider the impact after changing the root of the answer:

Obviously from this point it is still on the path to the root node:

We each point on the path set $ p_ {1}, p_ {2}, ... p_ {dep} $ (in order)

Set to a point $ p_ {i} $, when at $ 1 $ is the root of the subtree point right and to $ s_ {i} $, in order to $ p $ root point power and as $ s ^ { '} _ { i} $

Then we consider: for any $ i $, satisfies: $ s_ {i} + s ^ { '} _ {i + 1} = s_ {1} = s ^ {'} _ {dep} $

That is the whole point of the tree and the right node is equal to a half of the right point and the right point and the lower half +

So we now look to derive the answer:

$ 1 $ provided to the root of the answer is $ ans_ {1} $

那么$ans=ans_{1}-\sum_{i=1}^{dep}s_{i}^{2}+\sum_{i=1}^{dep}(s^{'}_{i})^{2}$

With the above expression gives:

$ans=ans_{1}-\sum_{i=1}{dep}s_{i}^{2}+\sum_{i=1}^{dep-1}(s_{1}-s_{i+1})^{2}+(s^{'}_{dep})^{2}$

So that is:

$ans=ans_{1}-\sum_{i=1}^{dep}s_{i}^{2}+deps_{1}^{2}-2s_{1}\sum_{i=2}^{dep}s_{i}+\sum_{i=2}^{dep}s_{i}^{2}$

then:

$ans=ans_{1}+(dep-1)s_{1}^{2}-2s_{1}\sum_{i=1}^{dep}s_{i}+2s_{1}$

Sort out:

$ans=ans_{1}+s_{1}[(dep+1)s_{1}-2\sum_{i=1}^{dep}s_{i}]$

Therefore, we still need to maintain $ s_ {i} $ to

Such tree cross + segment tree can be the perfect solution to this problem

Paste the code:

// luogu-judger-enable-o2
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#define rt1 rt<<1
#define rt2 (rt<<1)|1
#define ll long long
using namespace std;
struct Edge
{
    int nxt,to;
}edge[400005];
struct Seg_tree
{
    ll lazy,sum;
}tree[800005 ];
int head [ 200005 ];
int cnt = 1 ;
int siz [ 200005 ], son [ 200005 ], nnum [ 200005 ], ful [ 200005 ], ttop [ 200005 ] dep [ 200005 ] f [ 200005 ]; 
II w [ 200005 ], s [ 200005 ];
int so many; 
II ans = 0 ;
int n, m;
void Add ( int i, int i) 
{ 
    Edge [cut] .nxt =head[l];
    edge[cnt].to=r;
    head[l]=cnt++;
}
void dfs(int x,int fx)
{
    siz[x]=1,f[x]=fx,dep[x]=dep[fx]+1,s[x]=w[x];
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int to=edge[i].to;
        if(to==fx)continue;
        dfs(to,x);
        siz[x]+=siz[to],s[x]+=s[to],son[x]=siz[son[x]]<siz[to]?to:son[x];
    }
    ans+=s[x]*s[x];
}
void redfs(int x,int topx,int fx)
{
    ttop[x]=topx,nnum[x]=++tot,onum[tot]=x;
    if(son[x])redfs(son[x],topx,x);
    for(int i=head[x];i;i=edge[i].nxt)
    {
        int to=edge[i].to;
        if(to==fx||to==son[x])continue;
        redfs(to,to,x);
    }
}
void buildtree(int rt,int l,int r)
{
    if(l==r){tree[rt].sum=s[onum[l]];return;}
    int mid=(l+r)>>1;
    buildtree(rt1,l,mid),buildtree(rt2,mid+1,r);
    tree[rt].sum=tree[rt1].sum+tree[rt2].sum;
}
void pushdown(int rt,int l,int r)
{
    tree[rt1].lazy+=tree[rt].lazy,tree[rt2].lazy+=tree[rt].lazy;
    int mid=(l+r)>>1;
    tree[rt1].sum+=(mid-l+1)*tree[rt].lazy,tree[rt2].sum+=(r-mid)*tree[rt].lazy;
    tree[rt].lazy=0;
}
void update(int rt,int l,int r,int lq,int rq,ll v)
{
    if(l>=lq&&r<=rq)
    {
        tree[rt].lazy+=v,tree[rt].sum+=(r-l+1)*v;
        return;
    }
    if(tree[rt].lazy)pushdown(rt,l,r);
    int mid=(l+r)>>1;
    if(lq<=mid)update(rt1,l,mid,lq,rq,v);
    if(rq>mid)update(rt2,mid+1,r,lq,rq,v);
    tree[rt].sum=tree[rt1].sum+tree[rt2].sum;
}
ll query(int rt,int l,int r,int lq,int rq)
{
    if(l>=lq&&r<=rq)return tree[rt].sum;
    int mid=(l+r)>>1;
    if(tree[rt].lazy)pushdown(rt,l,r);
    ll ret=0;
    if(lq<=mid)ret+=query(rt1,l,mid,lq,rq);
    if(rq>mid)ret+=query(rt2,mid+1,r,lq,rq);
    return ret;
}
void pushup(int x,ll v)
{
    while(x){update(1,1,n,nnum[ttop[x]],nnum[x],v),x=f[ttop[x]];}
}
ll l_query(int x)
{
    ll ret=0;
    while(x){ret+=query(1,1,n,nnum[ttop[x]],nnum[x]),x=f[ttop[x]];}
    return ret;
}
template <typename T>inline void read(T &x)
{
    T f=1,c=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
    x=c*f;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++)
    {
        int x,y;
        read(x),read(y);
        add(x,y),add(y,x);
    }
    for(int i=1;i<=n;i++)read(w[i]);
    dfs(1,0),redfs(1,1,1);
    buildtree(1,1,n);
    while(m--)
    {
        int typ;
        read(typ);
        if(typ==1)
        {    
            int x;
            ll v;
            read(x),read(v);
            ans+=(v-w[x])*(v-w[x])*dep[x];
            ans+=2*(v-w[x])*l_query(x);
            pushup(x,v-w[x]);
            w[x]=v;
        }else
        {
            int x;
            read(x);
            ll temp1=query(1,1,n,nnum[1],nnum[1]);
            ll temp2=l_query(x);
            ll temps= temp1 * ((dep [x] + 1 ) * temp1- 2 * temp2); 
            printf ( " % lld \ n " , year + time); 
        } 
    } 
    Return  0 ; 
}

 

Guess you like

Origin www.cnblogs.com/zhangleo/p/11161619.html