ACM-ICPC 2018 network Shenyang Division Preliminary J. Ka Chang (DFS tree block sequence + + segment tree)

The meaning of problems

Links: https://nanti.jisuanke.com/t/A1998

Given a rooted tree (root 1), there are n nodes. When the initial value of each node is below 0. q operations, there are two operations, the operation to a depth of 1 L (root depth 0) all increase the value of the point X. 2. Operation of the query result is the x subtree rooted and worth. Wherein N, Q <= 1e5.

Thinking

Because this problem is all the points of a certain depth plus x, so it is not a tree chain split.

We can first look dfs pretreatment sequence, incidentally d [u]: u depth, dd [x]: the depth of the point x requirements set out.

Consider block, to a depth of two cases: a number of points of this depth <= block; 2 the number of points of this depth.> Block..

In the case of 1: We can update violence, because sqrt (n) block I is taken, then the update is the worst of the complexity of O (q log (the n-) sqrt (the n-)), can accept, after all the data is not particularly strong.

In the case of 2: We direct this layer plus x, i.e. add [deep] + = x.

For query operations, we first calculate the tree line at this point is the value of the sub-tree root, of course, update the segment tree only violence size <= layer block, so the query will only query value on these layers. We also calculate the size> block layers, how to calculate it?

We define a map <ll, ll> M [N], M [u] and expressed as u (size> block layer) value the sub-root of the tree, can enumerate each point M, if the the point where the layer size> block, the point is that all fathers have contributed to it, so the climb, father plus contribution to this point. So size> value of the block of layers we can easily be obtained by M.

Code

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
#define int ll
const int N=200005;
const double eps=1e-8;
const double PI = acos(-1.0);
struct node
{
    int to,next;
} eg[N];
int head[N],tot=0,sum[N<<2],add[N];
void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}
void addedge(int u,int v)
{
    eg[tot].to=v;
    eg[tot].next=head[u];
    head[u]=tot++;
}
int in[N],out[N],id=0,q[N],d[N],block,f[N];
vector<int> dd[N];
map<ll,ll> M[N];
void dfs(int x,int fa,int deep)
{
    q[++id]=x;
    in[x]=id;
    d[x]=deep;
    f[x]=fa;
    dd[deep].push_back(x);
    for(int i=head[x]; ~i; i=eg[i].next)
    {
        if(eg[i].to!=fa)
        {
            dfs(eg[i].to,x,deep+1);
        }
    }
    out[x]=id;
}
void pushUp(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=0;
        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    pushUp(rt);
}
void update(int L,int c,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]+=c;
        return ;
    }
    int m=(l+r)>>1;
    if(m>=L)    update(L,c,l,m,rt<<1);
    else        update(L,c,m+1,r,rt<<1|1);
    pushUp(rt);

}
int query(int L,int R,int l,int r,int rt)
{
    if(l>=L&&r<=R)
    {
        return sum[rt];
    }
    int m=(l+r)>>1;
    int ans=0;
    if(m>=L)
        ans+=query(L,R,l,m,rt<<1);
    if(m<R)
        ans+=query(L,R,m+1,r,rt<<1|1);
    return ans;
}
ll ask(int rt)
{
    map<ll,ll>::iterator it=M[rt].begin();
    ll res=0;
    for(;it!=M[rt].end();it++)
    {
        res+=(it->second)*add[it->first];
    }
    return res;
}
signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    std::cout.tie(0);
    int n,q;
    while(cin>>n>>q)
    {
        id=0;
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        init();
        for(int i=0; i<n-1; i++)
        {
            int a,b;
            cin>>a>>b;
            addedge(a,b);
            addedge(b,a);
        }
        block=sqrt(n);
        dfs(1,0,0);
        build(1,n,1);
        for(int i=1; i<=n; i++)
        {
            if(dd[d[i]].size()>block)
            {
                int u=i;
                while(u)
                {
                    if(!M[u][d[i]])
                        M[u][d[i]]=1;
                    else
                        M[u][d[i]]++;
                    u=f[u];
                }
            }
        }
    //   for(int i=1;i<=n;i++)
     //       cout<<i<<" "<<in[i]<<" "<<out[i]<<endl;
        while(q--)
        {
            int o,a,b;
            cin>>o>>a;
            if(o==1)
            {
                cin>>b;
                if(dd[a].size()>block)
                {
                    add[a]+=b;
                }
                else
                {
                    int sz=dd[a].size();
                    for(int i=0;i<sz;i++)
                    {
                        int u=dd[a][i];
                        update(in[u],b,1,n,1);
                    }
                }
            }
            else
            {

                cout<<query(in[a],out[a],1,n,1)+ask(a)<<endl;
            }
        }
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/mcq1999/p/11420127.html