Little M s attack plan The Preliminary Contest for ICPC Asia Xuzhou 2019

官方题解说的很清楚了,提供一个实现。

改了一年bug,过于菜了...

 

#include<bits/stdc++.h>

using namespace std;
#define lowbit(x) ((x)&(-x))
#define REP(i, a, n) for(int i=a;i<=(n);i++)
#define IOS ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> P;
const int maxn = 1e5 + 10;
const int N = 1e6 + 10;
const int M = 2e6 + 10;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const int mod2 = 998244353;
const int mod3 = 1e9 + 9;
const int hash1 = 131;
const int hash2 = 13331;
int tot;
int head[N], nxt[M], ver[M];

void addedge(int x, int y)
{
    ver[++tot] = y, nxt[tot] = head[x], head[x] = tot;
}

ll ans[5005];

struct query
{
    int k, op, id;

    query(int k, int op, int id) : k(k), op(op), id(id)
    {
        //cout << " k == " << k << " op == " << op << " id == " << id << endl;
    }
};

vector<query> q[N];
ll val[N];
int fa[N];

void dfs(int x, int pre)
{
    fa[x] = pre;
    for (int i = head[x]; i; i = nxt[i])
    {
        int y = ver[i];
        if (y != pre)
            dfs(y, x);
    }
}

ll c[N];

void add(int x, ll val)
{
    for (int i = x; i < N; i += lowbit(i))
        c[i] += val;
}

ll ask(int x)
{
    ll ans = 0;
    for (int i = x; i > 0; i -= lowbit(i))
        ans += c[i];
    return ans;
}

void dfs2(int x, int dep)
{
    for (int i = 0; i < q[x].size(); i++)
    {
        ll t = -q[x][i].op * (ask(q[x][i].k + dep) - ask(dep - 1));
        ans[q[x][i].id] += t;
    }
    add(dep, val[x]);

    for (int i = head[x]; i; i = nxt[i])
    {
        int y = ver[i];
        if (y == fa[x])
            continue;
        dfs2(y, dep + 1);
    }
    for (int i = 0; i < q[x].size(); i++)
    {
        ll t = q[x][i].op * (ask(q[x][i].k + dep) - ask(dep - 1));
        ans[q[x][i].id] += t;
    }
}

int main()
{
    IOS;
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
        cin >> val[i];
    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        addedge(u, v);
        addedge(v, u);
    }
    dfs(1, 0);
    int m;
    cin >> m;
    for (int i = 1; i <= m; i++)
    {
        int v, k;
        cin >> v >> k;
        q[v].push_back(query(k, 1, i));
        k--;
        while (v != 1 && k >= 0)
        {
            if (k > 0)
                q[v].push_back(query(k - 1, -1, i));
            v = fa[v];
            q[v].push_back(query(k, 1, i));
            k--;
        }
    }
    dfs2(1, 1);
    for (int i = 1; i <= m; i++)
    {
        cout << ans[i] << endl;
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值