zoukankan      html  css  js  c++  java
  • 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
    ", 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 }
  • 相关阅读:
    洛谷 P1508 Likecloud-吃、吃、吃
    Codevs 1158 尼克的任务
    2017.10.6 国庆清北 D6T2 同余方程组
    2017.10.6 国庆清北 D6T1 排序
    2017.10.3 国庆清北 D3T3 解迷游戏
    2017.10.3 国庆清北 D3T2 公交车
    2017.10.3 国庆清北 D3T1 括号序列
    2017.10.4 国庆清北 D4T1 财富
    2017.10.7 国庆清北 D7T2 第k大区间
    2017.10.7 国庆清北 D7T1 计数
  • 原文地址:https://www.cnblogs.com/baocong/p/6527426.html
Copyright © 2011-2022 走看看