Ka Chang ACM-ICPC 2018 沈阳赛区网络预赛 分块

题目链接:Ka Chang

题解:把每层的个数分块,当修改的那层个数大于block时直接保存贡献,小于block时暴力用树状数组维护

#include<string.h>
#include<bits/stdc++.h>
#include<algorithm>
#include<queue>
#define ll long long
#define pb push_back
using namespace std;
#define INF 0xffffff
#define MAXN 300010
const int N=1e5+5;
vector<int>g[N],dep[N],p;
int block,in[N],out[N],n,q,cnt;
ll b[N],an[N];
int lowbit(int x)
{
    return x&-x;
}
void add(int x,int y)
{
    while(x<=n)
    {
        b[x]+=y;
        x+=lowbit(x);
    }
}
ll sum(int x)
{
    ll ans=0;
    while(x)
    {
        ans+=b[x];
        x-=lowbit(x);
    }
    return ans;
}

void dfs(int v,int f,int d)
{
    in[v]=++cnt;
    dep[d].pb(in[v]);
    for(int to:g[v])
    {
        if(to!=f)
        {
            dfs(to,v,d+1);
        }
    }
    out[v]=cnt;
}
int main()
{
    scanf("%d %d",&n,&q);
    for(int i=0;i<n-1;i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        g[u].pb(v);
        g[v].pb(u);
    }
    dfs(1,0,0);
    block=sqrt(n);
    for(int i=0;i<n;i++)
    {
        if(dep[i].size()>block)
        {
            p.pb(i);
        }
    }
    while(q--)
    {
        int op,val,w;
        scanf("%d%d",&op,&val);
        if(op==1)
        {
            scanf("%d",&w);
            if(dep[val].size()>block)an[val]+=w;
            else
            {
                for(int i=0;i<dep[val].size();i++)
                {
                    add(dep[val][i],w);
                }
            }
        }
        else
        {
            ll ans=sum(out[val])-sum(in[val]-1);
            for(int i=0;i<p.size();i++)
            {
                ans+=1ll*(upper_bound(dep[p[i]].begin(),dep[p[i]].end(),out[val])-lower_bound(dep[p[i]].begin(),dep[p[i]].end(),in[val]))*an[p[i]];

            }
            printf("%lld
",ans);
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lhclqslove/p/9635802.html