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 }

 

posted @ 2017-03-09 19:48  Flowersea  阅读(142)  评论(0编辑  收藏  举报