Codeforces Round #381 (Div. 2) D Alyona and a tree DFS+前缀和+二分查找
D. Alyona and a tree
链接:
http://codeforces.com/contest/740/problem/D
题解:
对于在v的子树中的u,dis(u,v)其实就是dep[u]-dep[v]<=a[u],移一下就是dep[u]-a[u]<=dep[v],
那么直接dfs下去,二分找到第一个大于等于左边的dep[v],那么相当于一个区间前缀和嘛,
然后dfs完统计答案并且把结点pop掉。
代码:
1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <cstring> 10 #include <sstream> 11 #include <iostream> 12 #include <algorithm> 13 #include <functional> 14 using namespace std; 15 #define rep(i,a,n) for (int i=a;i<=n;i++) 16 #define per(i,a,n) for (int i=n;i>=a;i--) 17 #define pb push_back 18 #define mp make_pair 19 #define all(x) (x).begin(),(x).end() 20 #define SZ(x) ((int)(x).size()) 21 typedef vector<int> VI; 22 typedef long long ll; 23 typedef pair<int, int> PII; 24 const ll mod = 1e9 + 7; 25 const int inf = 0x3f3f3f3f; 26 const double eps = 1e-7; 27 // head 28 29 const int maxn = 2e5 + 7; 30 vector<pair<int, ll> > e[maxn]; 31 vector<pair<ll, int> > path; 32 ll a[maxn], dep[maxn], ans[maxn]; 33 34 void dfs(int u){ 35 ans[u]++; 36 int p = lower_bound(path.begin(), path.end(), make_pair(dep[u] - a[u], -1)) - path.begin(); 37 p--; 38 if (p >= 0) ans[path[p].second]--; 39 path.pb(mp(dep[u], u)); 40 for (int i = 0; i < e[u].size(); i++){ 41 int v = e[u][i].first; 42 ll w = e[u][i].second; 43 dep[v] = dep[u] + w; 44 dfs(v); 45 ans[u] += ans[v]; 46 } 47 path.pop_back(); 48 } 49 50 int main(){ 51 ios::sync_with_stdio(false); 52 int n; 53 cin >> n; 54 rep(i, 1, n) cin >> a[i]; 55 rep(i, 2, n) { 56 int p; ll w; 57 cin >> p >> w; 58 e[p].pb(mp(i, w)); 59 } 60 dfs(1); 61 rep(i, 1, n) cout << ans[i] - 1 << " "; 62 return 0; 63 }
树状数组
1 #include <map> 2 #include <set> 3 #include <cmath> 4 #include <queue> 5 #include <stack> 6 #include <cstdio> 7 #include <string> 8 #include <vector> 9 #include <cstring> 10 #include <sstream> 11 #include <iostream> 12 #include <algorithm> 13 #include <functional> 14 using namespace std; 15 #define rep(i,a,n) for (int i=a;i<=n;i++) 16 #define per(i,a,n) for (int i=n;i>=a;i--) 17 #define pb push_back 18 #define mp make_pair 19 #define all(x) (x).begin(),(x).end() 20 #define SZ(x) ((int)(x).size()) 21 typedef vector<int> VI; 22 typedef long long ll; 23 typedef pair<int, int> PII; 24 const ll mod = 1e9 + 7; 25 const int inf = 0x3f3f3f3f; 26 const double eps = 1e-7; 27 // head 28 29 #define LL long long 30 const int maxn = 2e5 + 5; 31 int a[maxn], in[maxn], out[maxn], c[maxn], ans[maxn]; //a-每个点的值,in-dfs该点的顺序,out-该点的子树最远的叶子 32 LL dis[maxn]; //每个点到根的距离 33 vector<int> g[maxn], w[maxn]; //g-建树,w-每条边的值 34 int n, ord = 0; 35 36 struct node { 37 int tp, id; 38 LL v; 39 node(){} 40 node(int a, int b, LL c) { 41 tp = a, id = b, v = c; 42 } 43 } b[maxn * 2]; 44 45 bool cmp(node a, node b) { 46 if (a.v == b.v) return a.tp < b.tp; 47 return a.v < b.v; 48 } 49 50 void dfs(int x, LL d) { //dfs in-标记每个点遍历的顺序,out-该点的子树最远的叶子,dis-该点到根节点的距离 51 dis[x] = d; 52 in[x] = ++ord; 53 for (int i = 0; i < g[x].size(); i++) { 54 dfs(g[x][i], d + w[x][i]); 55 } 56 out[x] = ord; 57 } 58 59 void add(int x) { 60 while (x <= n) { 61 c[x]++; 62 x += x&-x; //lowbit直接写在函数里面,看起来简洁些 63 } 64 } 65 66 int query(int x) { 67 int ans = 0; 68 while (x) { 69 ans += c[x]; 70 x -= x&-x; 71 } 72 return ans; 73 } 74 75 int main() { 76 scanf("%d", &n); 77 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 78 for (int i = 2; i <= n; i++) { 79 int u, v; 80 scanf("%d%d", &u, &v); 81 g[u].pb(i); 82 w[u].pb(v); 83 } 84 dfs(1, 0); 85 int cnt = 0; 86 for (int i = 1; i <= n; i++) { 87 b[++cnt] = node(1, i, dis[i] - a[i]); 88 b[++cnt] = node(2, i, dis[i]); 89 } 90 sort(b + 1, b + 1 + cnt, cmp); 91 for (int i = 1; i <= cnt; i++) printf("%d %d %I64d\n", b[i].tp, b[i].id, b[i].v); 92 memset(c, 0, sizeof(c)); 93 for (int i = 1; i <= cnt; i++) { 94 if (b[i].tp == 1) add(in[b[i].id]); 95 else { 96 ans[b[i].id] = query(out[b[i].id]) - query(in[b[i].id] - 1); 97 } 98 } 99 for (int i = 1; i <= n; i++) 100 printf("%d ", ans[i] - 1); //得到的答案包含它本身,所以要减一 101 puts(""); 102 }