ACM-ICPC 2018 沈阳赛区网络预赛

J. Ka Chang

昨天学弟写的,感觉题目挺好的,今天写了写。

和以前分块一样,但这题很难想到用分块做。

像是一次操作大量的区间单点修改,区间查询……

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 5;
int cnt[205][maxn];
ll val[maxn];
vector<int> g[maxn];
int ord[maxn];
int L[maxn], R[maxn], depth[maxn];
int ind = 0;
void dfs(int u, int fa, int dep)
{
    L[u] = ++ind;
    ord[ind] = u;
    depth[ind] = dep;
    for(int i = 0; i < g[u].size(); i++)
    {
        int v = g[u][i];
        if(v == fa) continue;
        dfs(v, u, dep + 1);
    }
    R[u] = ind;
}
int posl[205], posr[205];
int pos[maxn];
ll sum[205];
int t = 0;
void change(int dep,int x)
{
    val[dep] += (ll)x;
    for(int i = 1; i <= t; i++)
    {
        sum[i] += (ll)x * cnt[i][dep];
    }
}
ll query(int l, int r)
{
    int p = pos[l], q = pos[r];
    ll ans = 0;
    if(p == q)
    {
        for(int i = l; i <= r; i++)
        {
            ans += val[depth[i]];
        }
    }
    else
    {
        for(int i = p + 1; i <= q - 1; i++)
        {
            ans += sum[i];
        }
        for(int i = l; i <= posr[p]; i++)
        {
            ans += val[depth[i]];
        }
        for(int i = posl[q]; i <= r; i++)
        {
            ans += val[depth[i]];
        }
    }
    return ans;
}
int main()
{
    int n, q; scanf("%d %d", &n, &q);
    for(int i = 1; i <= n - 1; i++)
    {
        int u, v; scanf("%d %d", &u, &v);
        g[u].push_back(v);
        g[v].push_back(u);
    }
    dfs(1, -1, 0);
    t = min(200, (int)sqrt(n));
    int len = n / t;
    for(int i = 1; i <= t; i++)
    {
        posl[i] = (i - 1) * len + 1;
        posr[i] = i * len;
    }
    if(posr[t] < n) t++, L[t] = R[t - 1] + 1, R[t] = n;
    ///预处理
    for(int i = 1; i <= t; i++)
    {
        for(int j = posl[i]; j <= posr[i]; j++)
        {
            pos[j] = i;
            cnt[i][depth[j]]++;
        }
    }
    while(q--)
    {
        int op, l, x;
        scanf("%d", &op);
        if(op == 1)
        {
            scanf("%d %d", &l, &x);
            change(l, x);
        }
        else
        {
            scanf("%d", &x);
            printf("%lld\n", query(L[x], R[x]));
        }
    }
    return 0;
}
Code

 

posted @ 2018-09-09 10:18  卷珠帘  阅读(230)  评论(0编辑  收藏  举报