首页 > 代码库 > D. Alyona and a tree 公式转换 + 分块暴力

D. Alyona and a tree 公式转换 + 分块暴力

http://codeforces.com/problemset/problem/740/D

对于每一对<u, v>。设dis[u]表示root到点u的距离,那么dis<u去v>就是dis[v] - dis[u],

就是在它的儿子中找出有多少个v使得dis[v] - dis[u] <= a[v]。然后,因为如果v确定了,那么dis[v]和a[v]就确定了。

所以把公式转换为dis[v] - a[v] <= dis[u]。

那么可以暴力枚举每一个u,然后在其儿子中找有多少个数小于等于它,这个可以直接暴力分块。

技术分享
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = 2e5 + 20;
struct node {
    int u, v, w;
    int tonext;
}e[maxn];
int first[maxn];
int num;
void add(int u, int v, int w) {
    ++num;
    e[num].u = u;
    e[num].v = v;
    e[num].w = w;
    e[num].tonext = first[u];
    first[u] = num;
}
int a[maxn];
int ans[maxn];
LL dp[maxn];
struct LIST {
    int id;
    LL val;
}List[maxn];
int lenList;
int DFN;
int L[maxn];
int R[maxn];
void dfs(int cur) {
    List[++lenList].id = cur;
//    List[lenList].val = a[cur];
    ++DFN;
    L[cur] = DFN;
    for (int i = first[cur]; i; i = e[i].tonext) {
        int v = e[i].v;
        dp[v] = dp[e[i].u] + e[i].w;
        dfs(v);
    }
    R[cur] = DFN;
}
LL tosort[maxn];
void work() {
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++i) {
        scanf("%d", &a[i]);
    }
    for (int i = 1; i <= n - 1; ++i) {
        int fa, w;
        scanf("%d%d", &fa, &w);
        add(fa, i + 1, w);
    }
    dfs(1);
    for (int i = 1; i <= lenList; ++i) {
        List[i].val = dp[List[i].id] - a[List[i].id];
        tosort[i] = List[i].val;
//        printf("%d ", List[i].id);
//        printf("%d %d\n", L[List[i].id], R[List[i].id]);
    }
    int magic = (int)sqrt(lenList);
    for (int i = 1; i <= lenList;) {
        if (i + magic - 1 <= lenList) {
            sort(tosort + i, tosort + i + magic);
        } else break;
        i += magic;
    }
    for (int i = 1; i <= n; ++i) {
        for (int j = L[i] + 1; j <= R[i];) {
            if (j % magic == 1 && j + magic - 1 <= R[i]) {
                int pos = upper_bound(tosort + j, tosort + j + magic, dp[i]) - (tosort + j - 1);
                ans[i] += pos - 1;
                j += magic;
            } else {
                if (dp[i] >= List[j].val) {
                    ans[i]++;
                }
                j++;
            }
        }
    }
    for (int i = 1; i <= n; ++i) {
        printf("%d ", ans[i]);
    }
}
int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code

 

D. Alyona and a tree 公式转换 + 分块暴力