• 2016-2017 CT S03E07: Codeforces Trainings Season 3 Episode 7


    A. Yet Another Problem with Strings

    题意:

    给出$n$个字符串$S_i$,要求支持两种操作:

    • 在第$i$个字符串后增加一个字符$c$
    • 给出一个字符串$T$,询问是否有一个串$S_i$是$T$的子串。

    强制在线,保证$sum S_i, sum T leq 2 cdot 10^5$

    思路:

    考虑暴力做法即枚举每个$S_i$然后询问$T$中的每个等长的子串是否等于$S_i$。

    但是一个小优化是可以把所有长度相同的$S_i$放在一起做,用std::map记录哈希值。

    并且注意到$sum S_i leq 2 cdot 10^5$,所以所有的$S_i$只有$sqrt{2 cdot 10^5}$种长度。

    暴力即可。

    B. Pen Pineapple Apple Pen

    Solved.

    题意:将一个序列合并成一个数。

    思路:分类讨论一下, 水。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int maxn = 1e5 + 10;
     6 
     7 char str[maxn];
     8 
     9 bool solve()
    10 {
    11     int len = strlen(str + 1);
    12     if(len == 1) return true;
    13     while(len % 2 == 0) len = len >> 1;
    14     if(len != 1) return false;
    15     len = strlen(str + 1);
    16     for(int i = 1; i <= len; i += 2) if(str[i] != 'P' && str[i + 1] != 'P') return false;
    17     return true;
    18 }
    19 
    20 int main()
    21 {
    22     int t;
    23     scanf("%d", &t);
    24     while(t--)
    25     {
    26         scanf("%s", str + 1);
    27         puts(solve() ? "YES" : "NO");
    28     }
    29     return 0;
    30 }
    View Code

    C. Stickmen

    Solved.

    题意:找有几个小人

    思路:枚举$i, j$两个点作为中间那条线的端点, 再枚举公共点计算贡献。

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 const ll MOD = 1e9 + 7;
     8 const int maxn = 1e3;
     9 
    10 int n, m;
    11 ll fac[maxn];
    12 ll inv[maxn];
    13 ll invfac[maxn];
    14 int du[maxn];
    15 int mp[maxn][maxn];
    16 
    17 void Init()
    18 {
    19     fac[1] = inv[1] = invfac[1] = 1;
    20     fac[0] = inv[0] = invfac[0] = 1;
    21     for(int i = 2; i < maxn; ++i)
    22     {
    23         fac[i] = fac[i - 1] * i % MOD;
    24         inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
    25         invfac[i] = invfac[i - 1] * inv[i] % MOD;
    26     }
    27 }
    28 
    29 ll C(int n, int m)
    30 {
    31     if(n < 0 || m < 0) return 0;
    32     if(m > n) return 0;
    33     return fac[n] * invfac[m] % MOD * invfac[n - m] % MOD;
    34 }
    35 
    36 int merge(int x, int y)
    37 {
    38     int res = 0;
    39     for(int i = 1; i <= n; ++i) if(mp[x][i] == 1 && mp[y][i] == 1) res++;
    40     return res;
    41 }
    42 
    43 int main()
    44 {
    45     Init();
    46     while(~scanf("%d %d", &n, &m))
    47     {
    48         memset(mp, 0, sizeof mp);
    49         memset(du, 0, sizeof du);
    50         for(int i = 1, x, y; i <= m; ++i)
    51         {
    52             scanf("%d %d", &x, &y);
    53             du[x]++, du[y]++;
    54             mp[x][y] = mp[y][x] = 1;
    55         }
    56         ll ans = 0;
    57         for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) if(mp[i][j] && i != j)
    58         {
    59             int x = du[i] - 1, y = du[j] - 1;
    60             int same = merge(i, j);
    61             ans = (ans  + C(x, 3) * C(y, 2) % MOD)% MOD;
    62             
    63             ans = (ans - C(x - 1, 2) * C(y - 1, 1) % MOD * same % MOD) % MOD;
    64             ans = (ans + C(x - 2, 1) * C(same, 2) % MOD) % MOD;
    65         }
    66         printf("%lld
    ", ans);
    67     }
    68     return 0;
    69 }
    View Code

    D. Strange Queries

    Solved.

    题意:询问$i in [L_1, R_1],j in [L_2, R_2]  有多少对(i, j) 使得 a_i = a_j$

    思路:$f[i][j]表示第i个块对前j个块的贡献,f2[i][j]表示a_i对前j个块的贡献$

    $整块整块处理,边边角角处理$

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define ll long long
      5 #define N 50010
      6 #define S 150
      7 #define unit 450
      8 int n, a[N], q;
      9 int pos[N], posl[unit], posr[unit];
     10 ll f[unit][unit], f2[N][unit];
     11 int cnt[N];
     12 
     13 int main()
     14 {
     15     while (scanf("%d", &n) != EOF)
     16     {
     17         for (int i = 1; i <= n; ++i) pos[i] = (i - 1) / S + 1;
     18         for (int i = 1; i <= n; ++i)
     19         {
     20             if (i == 1 || pos[i] != pos[i - 1]) 
     21                 posl[pos[i]] = i;
     22 //            cout << i << " " << pos[i] << endl;
     23             posr[pos[i]] = i;  
     24 //            printf("%d %d
    ", posl[pos[i]], posr[pos[i]]);
     25         }
     26 //        for (int i = 1; i <= n; ++i) cout << i << " " << pos[i] << endl;
     27 //        for (int i = 1; i <= n; ++i)
     28 //            printf("%d %d
    ", posl[pos[i]], posr[pos[i]]);
     29         memset(f, 0, sizeof f);
     30         memset(f2, 0, sizeof f2); 
     31         memset(cnt, 0, sizeof cnt);
     32         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
     33         for (int i = 1; i <= pos[n]; ++i)   
     34         {  
     35             for (int j = posl[i]; j <= posr[i]; ++j)
     36                 ++cnt[a[j]];
     37             for (int j = 1; j <= n; ++j) 
     38             {
     39                 f[i][pos[j]] += cnt[a[j]];
     40                 f2[j][i] += cnt[a[j]];
     41             }
     42             for (int j = posl[i]; j <= posr[i]; ++j)
     43                 --cnt[a[j]];
     44         } 
     45         for (int i = 1; i <= pos[n]; ++i)
     46             for (int j = 1; j <= pos[n]; ++j)
     47                 f[i][j] += f[i][j - 1];
     48         for (int i = 1; i <= n; ++i)
     49             for (int j = 1; j <= pos[n]; ++j)
     50                 f2[i][j] += f2[i][j - 1]; 
     51         scanf("%d", &q);
     52         int l[2], r[2];
     53         while (q--)
     54         {
     55             for (int i = 0; i < 2; ++i)
     56                 scanf("%d%d", l + i, r + i);
     57             if (pos[l[1]] == pos[r[1]])
     58             {
     59                 swap(l[0], l[1]);
     60                 swap(r[0], r[1]);
     61             }
     62             ll res = 0; 
     63             if (pos[l[0]] == pos[r[0]])
     64             {
     65                 if (pos[l[1]] == pos[r[1]])
     66                 {
     67                     for (int i = l[0]; i <= r[0]; ++i) 
     68                         ++cnt[a[i]];
     69                     for (int i = l[1]; i <= r[1]; ++i) 
     70                         res += cnt[a[i]];
     71                     for (int i = l[0]; i <= r[0]; ++i)
     72                         --cnt[a[i]];
     73                 }
     74                 else
     75                 {
     76                     int L = pos[l[1]] + 1;
     77                     int R = pos[r[1]] - 1;
     78                     for (int i = l[0]; i <= r[0]; ++i)
     79                     {
     80                         res += f2[i][R] - f2[i][L - 1];
     81                         ++cnt[a[i]];
     82                     }
     83                     for (int i = l[1]; i <= posr[pos[l[1]]]; ++i)
     84                         res += cnt[a[i]];
     85                     for (int i = posl[pos[r[1]]]; i <= r[1]; ++i)
     86                         res += cnt[a[i]];
     87                     for (int i = l[0]; i <= r[0]; ++i)
     88                         --cnt[a[i]];
     89                 }
     90             }
     91             else
     92             {
     93                 int L[2] = {pos[l[0]] + 1, pos[l[1]] + 1};
     94                 int R[2] = {pos[r[0]] - 1, pos[r[1]] - 1};
     95                 for (int i = L[0]; i <= R[0]; ++i)
     96                     res += f[i][R[1]] - f[i][L[1] - 1]; 
     97                 for (int i = l[0]; i <= posr[pos[l[0]]]; ++i) 
     98                 {
     99                     res += f2[i][R[1]] - f2[i][L[1] - 1];
    100                     ++cnt[a[i]];
    101                 }
    102                 for (int i = posl[pos[r[0]]]; i <= r[0]; ++i)
    103                 {
    104                     res += f2[i][R[1]] - f2[i][L[1] - 1];
    105                     ++cnt[a[i]];
    106                 }
    107                 for (int i = l[1]; i <= posr[pos[l[1]]]; ++i) 
    108                 {
    109                     res += f2[i][R[0]] - f2[i][L[0] - 1];
    110                     res += cnt[a[i]];
    111                 }
    112                 for (int i = posl[pos[r[1]]]; i <= r[1]; ++i)
    113                 {
    114                     res += f2[i][R[0]] - f2[i][L[0] - 1];
    115                     res += cnt[a[i]];
    116                 }
    117                 for (int i = l[0]; i <= posr[pos[l[0]]]; ++i) 
    118                     --cnt[a[i]];
    119                 for (int i = posl[pos[r[0]]]; i <= r[0]; ++i)
    120                     --cnt[a[i]];
    121             }
    122             printf("%lld
    ", res);
    123         }
    124     }
    125     return 0;
    126 }
    View Code

    E. Bravebeart

    Solved.

    题意:给出n个人和n匹马, 每个人和每匹马都有自己的能力值, 每个人选择一匹马, 那么每个人的权值就是个人能力值乘上马的权值, 求是否存在一种方案, 使得第一个人的权值最大。

    思路:排序, 水

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 const int INF = 0x3f3f3f3f;
     6 const int maxn = 1e5 + 10;
     7 
     8 int n;
     9 int w[maxn], h[maxn];
    10 
    11 bool solve(int tmp)
    12 {
    13     for(int i = n - 1; i >= 1; --i)
    14     {
    15         if(w[i] * h[n - 1 - i + 1] >= tmp) return false; 
    16     }
    17     return true;
    18 }
    19 
    20 int main()
    21 {
    22     int t;
    23     scanf("%d", &t);
    24     while(t--)
    25     {
    26         scanf("%d", &n);
    27         for(int i = 1; i <= n; ++i) scanf("%d", w + i);
    28         for(int i = 1; i <= n; ++i) scanf("%d", h + i);
    29         int tmp = w[1];
    30         w[1] = INF;
    31         sort(w + 1, w + 1 + n);
    32         sort(h + 1, h + 1 + n);
    33         tmp *= h[n];
    34         puts(solve(tmp) ? "YES" : "NO");
    35     }
    36     return 0;
    37 }
    View Code

    F. GukiZ Height

    Solved.

    题意:$f_i = f_{i - 1} + a_{(i - 1) \% n +1}, g_i = h - frac{i cdot (i + 1)}{2}, 求最小的i 使得 f_i >= g_i$

    思路:枚举每个余数, 那么分为周期为0和周期>=1, 对于后面一种情况, 二分周期。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long 
     5 #define N 100010
     6 int n;
     7 ll h, a[N];
     8 ll sum[N];
     9 
    10 bool check(ll x, int remind)
    11 {
    12     ll day = x * n + remind;
    13     return h - (day * (day + 1)) / 2 <= sum[n] * x + sum[remind];
    14 }
    15 
    16 int main()
    17 {
    18     while (scanf("%d%lld", &n, &h) != EOF)
    19     {
    20         sum[0] = 0;
    21         for (int i = 1; i <= n; ++i) scanf("%lld", a + i);
    22         for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + a[i];
    23         ll ans = (ll)1e18; 
    24         for (int i = 1; i <= n; ++i) if(sum[i] >= h - (i * (i + 1) / 2)) ans = min(ans, 1ll * i);
    25         for (int i = 1; i <= n; ++i)
    26         {
    27             ll l = 0, r = (2e9 + 10) / n, res = -1;
    28             while (r - l >= 0)
    29             {
    30                 ll mid = (l + r) >> 1;
    31 //                cout << i << " " << mid << endl;
    32                 if (check(mid, i))
    33                 {
    34                     r = mid - 1;
    35                     res = mid;
    36                 }
    37                 else
    38                     l = mid + 1;
    39             }
    40 //            cout << i << " " << res << endl;
    41             if (res != -1) 
    42                 ans = min(ans, res * n + i); 
    43         }
    44         printf("%lld
    ", ans);
    45     }
    46     return 0;
    47 }
    View Code

    I. Prime Moving

    Solved.

    题意:将素数$a$通过某系列变化得到素数$b$, 每次变化可以加上或减去一个素数, 同时结果要求是素数。

    思路:将2作为中间点, 各种分类

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 typedef long long ll;
      6 
      7 const int S = 10;
      8 
      9 ll mult_mod(ll a, ll b, ll c)
     10 {
     11     a %= c;
     12     b %= c;
     13     ll ret = 0;
     14     ll tmp = a;
     15     while(b)
     16     {
     17         if(b & 1)
     18         {
     19             ret += tmp;
     20             if(ret > c) ret -= c;
     21         }
     22         tmp <<= 1;
     23         if(tmp > c) tmp -= c;
     24         b >>= 1;
     25     }
     26     return ret;
     27 }
     28 
     29 ll pow_mod(ll a, ll n, ll mod)
     30 {
     31     ll ret = 1;
     32     ll tmp = a % mod;
     33     while(n)
     34     {
     35         if(n & 1) ret = mult_mod(ret, tmp, mod);
     36         tmp = mult_mod(tmp, tmp, mod);
     37         n >>= 1;
     38     }
     39     return ret;
     40 }
     41 
     42 bool check(ll a, ll n, ll x, ll t)
     43 {
     44     ll ret = pow_mod(a, x, n);
     45     ll last = ret;
     46     for(int i = 1; i <= t; ++i)
     47     {
     48         ret = mult_mod(ret, ret, n);
     49         if(ret == 1 && last != 1 && last != n - 1) return true;
     50         last = ret;
     51     }
     52     if(ret != 1) return true;
     53     else return false;
     54 }
     55 
     56 bool is_Prime(ll n)
     57 {
     58     if(n < 2) return false;
     59     if(n == 2) return true;
     60     if((n & 1) == 0) return false;
     61     ll x = n - 1;
     62     ll t = 0;
     63     while((x & 1) == 0) { x >>= 1; ++t; }
     64     srand(time(NULL));
     65     for(int i = 0; i < S; ++i)
     66     {
     67         ll a = rand() % (n - 1) + 1;
     68         if(check(a, n, x, t)) return false;
     69     }
     70     return true;
     71 }
     72 
     73 ll a, b;
     74 
     75 void solve()
     76 {
     77     if(a == 2)
     78     {
     79         if(is_Prime(b - 2))
     80         {
     81             printf("%lld->%lld
    ", a, b);
     82             return ;
     83         }
     84         if(is_Prime(b + 2)) 
     85         {
     86             printf("%lld->%lld->%lld
    ", a, b + 2, b);
     87             return ;
     88         }
     89     }
     90     else
     91     {
     92         if(b == a + 2)
     93         {
     94             printf("%lld->%lld
    ", a, b);
     95             return ;
     96         }
     97         if(b == a + 4 && is_Prime(a + 2))
     98         {
     99             if(is_Prime(a - 2) && is_Prime(b - 2))
    100             {
    101                 puts("Poor Benny");
    102                 return ;
    103             }
    104             else
    105             {
    106                 printf("%lld->%lld->%lld
    ", a, a + 2, b);
    107                 return ;
    108             }
    109         }
    110         if(is_Prime(a - 2))
    111         {
    112             if(is_Prime(b - 2))
    113             {
    114                 printf("%lld->%lld->%lld
    ", a, 2ll, b);
    115                 return ;
    116             }
    117             if(is_Prime(b + 2))
    118             {
    119                 if(is_Prime(a + 2) && is_Prime(b - 2))
    120                 {
    121                     puts("Poor Benny");
    122                     return ;    
    123                 }
    124                 else
    125                 {
    126                     printf("%lld->%lld->%lld->%lld
    ", a, 2ll, b + 2, b);
    127                     return ;
    128                 }
    129             }
    130         }
    131         if(is_Prime(a + 2))
    132         {
    133             if(is_Prime(b - 2))
    134             {
    135                 printf("%lld->%lld->%lld->%lld
    ", a, a + 2, 2ll, b);
    136                 return ;
    137             }
    138             if(is_Prime(b + 2))
    139             {
    140                 printf("%lld->%lld->%lld->%lld->%lld
    ", a, a + 2, 2ll, b + 2, b);
    141                 return ;
    142             }
    143         }
    144     }
    145     puts("Unlucky Benny");
    146 }
    147 
    148 int main()
    149 {
    150     while(~scanf("%lld %lld", &a, &b))
    151     {
    152         solve();
    153     }
    154     return 0;
    155 }
    View Code

    J. Valentina and the Gift Tree

    Upsolved

    题意:给出一棵树,询问$a -> b的简单路径上组成的序列的最大子段和$

    思路:把一条简单路径拆成两条链,单独处理,一条链上用树链剖分处理,合并的时候注意左右端点怎么接

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define ll long long
      5 #define N 100010
      6 #define D 20
      7 #define INF 0x3f3f3f3f3f3f3f3f
      8 int n, q, g[N];
      9 vector <int> G[N];
     10 
     11 int sze[N], top[N], fa[D][N], son[N], p[N], fp[N], deep[N], cnt; 
     12 void DFS(int u)
     13 {
     14     sze[u] = 1; 
     15     for (int i = 1; i < D; ++i)
     16         fa[i][u] = fa[i - 1][fa[i - 1][u]]; 
     17     for (auto v : G[u]) if (v != fa[0][u])
     18     {
     19         fa[0][v] = u;  
     20         deep[v] = deep[u] + 1; 
     21         DFS(v);
     22         sze[u] += sze[v];
     23         if (!son[u] || sze[v] > sze[son[u]]) son[u] = v; 
     24     }
     25 }
     26 
     27 void gettop(int u, int sp)
     28 {
     29     top[u] = sp;
     30     p[u] = ++cnt;
     31     fp[cnt] = u;
     32     if (!son[u]) return;
     33     gettop(son[u], sp);
     34     for (auto v : G[u]) if (v != fa[0][u] && v != son[u])
     35         gettop(v, v);
     36 } 
     37 
     38 namespace SEG
     39 {
     40     struct node
     41     {
     42         ll lmax, rmax, Max, sum;
     43         node () {}
     44         void init()
     45         {
     46             lmax = rmax = Max = sum = -INF; 
     47         }
     48         node operator + (const node &other) const
     49         {
     50             node res; res.init();
     51             if (lmax == -INF || rmax == -INF)
     52                 return other; 
     53             if (other.lmax == -INF || other.rmax == -INF) 
     54                 return *this; 
     55             res.sum = sum + other.sum;
     56             res.lmax = max(lmax, sum + other.lmax);
     57             res.rmax = max(other.rmax, other.sum + rmax);
     58             res.Max = max(Max, other.Max);  
     59             res.Max = max(res.Max, rmax + other.lmax); 
     60             return res;
     61         }
     62     }a[N << 2], ans[2], tmp; 
     63     void build(int id, int l, int r)
     64     {
     65         a[id].init();
     66         if (l == r)
     67         {
     68             a[id].lmax = a[id].rmax = a[id].sum = a[id].Max = g[fp[l]];   
     69             return;
     70         }
     71         int mid = (l + r) >> 1;
     72         build(id << 1, l, mid);
     73         build(id << 1 | 1, mid + 1, r);
     74         a[id] = a[id << 1] + a[id << 1 | 1];
     75     }
     76     void query(int id, int l, int r, int ql, int qr)
     77     {
     78         if (qr < ql || ql <= 0 || qr <= 0) return; 
     79         if (l >= ql && r <= qr) 
     80         {
     81             tmp = tmp + a[id];
     82             return; 
     83         }
     84         int mid = (l + r) >> 1;
     85         if (ql <= mid) query(id << 1, l, mid, ql, qr);
     86         if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr); 
     87     }
     88 }
     89 
     90 int lca(int u, int v)
     91 {
     92     while (top[u] != top[v])
     93     {
     94         if (deep[top[u]] < deep[top[v]]) swap(u, v);
     95         u = fa[0][top[u]];
     96     }
     97     if (deep[u] > deep[v]) swap(u, v);
     98     return u;
     99 }
    100 
    101 int kth(int u, int k)
    102 {
    103     for (int i = 0; i < D; ++i) 
    104         if ((k >> i) & 1)
    105             u = fa[i][u]; 
    106     return u; 
    107 }
    108 
    109 void query(int u, int v, int vis)
    110 {
    111     SEG::ans[vis].init();
    112     while (top[u] != top[v])
    113     {
    114         if (deep[top[u]] < deep[top[v]]) swap(u, v);
    115         SEG::tmp.init();  
    116         SEG::query(1, 1, n, p[top[u]], p[u]);
    117         SEG::ans[vis] = SEG::tmp + SEG::ans[vis];
    118         u = fa[0][top[u]];
    119     }
    120     if (deep[u] > deep[v]) swap(u, v); 
    121     SEG::tmp.init();
    122     SEG::query(1, 1, n, p[u], p[v]);
    123     SEG::ans[vis] = SEG::tmp + SEG::ans[vis];
    124 }
    125 
    126 int main()
    127 {
    128     while (scanf("%d", &n) != EOF)  
    129     {
    130         for (int i = 1; i <= n; ++i) G[i].clear();
    131         memset(son, 0, sizeof son); cnt = 0; deep[1] = 0;
    132         for (int i = 1, u, v; i < n; ++i)
    133         {
    134             scanf("%d%d", &u, &v);
    135             G[u].push_back(v);
    136             G[v].push_back(u);
    137         }
    138         for (int i = 1; i <= n; ++i) scanf("%d", g + i);
    139         deep[1] = 0; fa[0][1] = 0;
    140         DFS(1); gettop(1, 1); SEG::build(1, 1, n);
    141         //if (n == 10) return 0;
    142         scanf("%d", &q); 
    143         int a, b;
    144         while (q--)
    145         {
    146             scanf("%d%d", &a, &b);
    147             if (deep[a] > deep[b]) swap(a, b);
    148             int Lca = lca(a, b);
    149             if (a == Lca) 
    150                 query(a, b, 0); 
    151             else
    152             {
    153                 query(Lca, a, 0);
    154                 query(kth(b, deep[b] - deep[Lca] - 1), b, 1);
    155                 swap(SEG::ans[0].lmax, SEG::ans[0].rmax);
    156                 SEG::ans[0] = SEG::ans[0] + SEG::ans[1];
    157             }
    158             printf("%lld
    ", SEG::ans[0].Max); 
    159         }
    160     }
    161     return 0;
    162 }
    View Code

    LCA

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 typedef long long ll;
      6 
      7 const ll MOD = 1e9 + 7;
      8 const ll INFLL = 0x3f3f3f3f3f3f3f3f;
      9 const int maxn = 1e5 + 10;
     10 
     11 const int DEG = 20;
     12 
     13 struct Edge {
     14     int to, nxt;
     15     Edge() {}
     16     Edge(int to, int nxt) :to(to), nxt(nxt) {}
     17 }edge[maxn << 1];
     18 
     19 struct node {
     20     ll lmax, rmax, ans, sum;
     21     node() 
     22     {
     23         sum = 0;
     24         lmax = rmax = ans = -INFLL;
     25     }
     26     node(ll tmp)
     27     {
     28         lmax = rmax = ans = sum = tmp;
     29     }
     30     node operator + (const node &other) const
     31     {
     32         node res;
     33         res.sum = sum + other.sum;
     34         res.lmax = max(lmax, sum + other.lmax);
     35         res.rmax = max(other.rmax, other.sum + rmax);
     36         res.ans = max(max(ans, other.ans), rmax + other.lmax);
     37         return res;
     38     }
     39 };
     40 
     41 int n, m;
     42 ll arr[maxn];
     43 int head[maxn], tot;
     44 node res[maxn][DEG];
     45 int fa[maxn][DEG];
     46 int deg[maxn];
     47 
     48 void Init()
     49 {
     50     tot = 0;
     51     memset(fa, -1, sizeof fa);
     52     memset(head, -1, sizeof head);
     53 }
     54 
     55 void addedge(int u, int v)
     56 {
     57     edge[tot] = Edge(v, head[u]); head[u] = tot++;
     58     edge[tot] = Edge(u, head[v]); head[v] = tot++;
     59     
     60 }
     61 
     62 void BFS(int root)
     63 {
     64     queue<int>q;
     65     deg[root] = 0;
     66     res[root][0] = node(arr[root]);
     67     fa[root][0] = root;
     68     q.push(root);
     69     while (!q.empty())
     70     {
     71         int tmp = q.front();
     72         q.pop();
     73         for (int i = 1; i < DEG; ++i)
     74         {
     75             fa[tmp][i] = fa[fa[tmp][i - 1]][i - 1];
     76             res[tmp][i] = res[tmp][i - 1] + res[fa[tmp][i - 1]][i - 1];
     77         }
     78         for (int i = head[tmp]; ~i; i = edge[i].nxt)
     79         {
     80             int v = edge[i].to;
     81             if (v == fa[tmp][0]) continue;
     82             deg[v] = deg[tmp] + 1;
     83             fa[v][0] = tmp;
     84             res[v][0] = node(arr[v]);
     85             q.push(v);
     86         }
     87     }
     88 }
     89 
     90 node LCA(int u, int v)
     91 {
     92     if (deg[u] > deg[v]) swap(u, v);
     93     int hu = deg[u], hv = deg[v];
     94     int tu = u, tv = v;
     95     node ansu, ansv;
     96     for (int det = hv - hu, i = 0; det; det >>= 1, ++i)
     97     {
     98         if (det & 1)
     99         {
    100             ansv = ansv + res[tv][i];
    101             tv = fa[tv][i];
    102         }
    103     }
    104     for (int i = DEG - 1; i >= 0; --i)
    105     {
    106         if (fa[tu][i] == fa[tv][i]) continue;
    107         ansu = ansu + res[tu][i];
    108         ansv = ansv + res[tv][i];
    109         tu = fa[tu][i];
    110         tv = fa[tv][i];
    111     }
    112     while (tu != tv)
    113     {
    114         ansu = ansu + res[tu][0];
    115         ansv = ansv + res[tv][0];
    116         tu = fa[tu][0];
    117         tv = fa[tv][0];
    118     }
    119     swap(ansv.lmax, ansv.rmax);
    120     return ansu + res[tu][0] + ansv;
    121 }
    122 
    123 void RUN()
    124 {
    125     while (~scanf("%d", &n))
    126     {
    127         Init();
    128         for (int i = 1, u, v; i < n; ++i)
    129         {
    130             scanf("%d %d", &u, &v);
    131             addedge(u, v);
    132         }
    133         for (int i = 1; i <= n; ++i) scanf("%lld", arr + i);
    134         BFS(1); 
    135         int q;
    136         scanf("%d", &q);
    137         for (int qq = 1, u, v; qq <= q; ++qq)
    138         {
    139             scanf("%d %d", &u, &v);
    140             printf("%lld
    ", LCA(u, v).ans);
    141         }
    142     }
    143 }
    144 
    145 int main()
    146 {
    147 #ifdef LOCAL_JUDGE
    148     freopen("Text.txt", "r", stdin);
    149 #endif // LOCAL_JUDGE
    150 
    151     RUN();
    152 
    153 #ifdef LOCAL_JUDGE
    154     fclose(stdin);
    155 #endif // LOCAL_JUDGE
    156     return 0;
    157 }
    View Code
  • 相关阅读:
    在vi或者vim中显示行号
    Ubuntu 14.10 下进程实时IO监控iotop命令详解
    Ubuntu 14.10 下网络流量实时监控ifstat iftop命令详解
    Ubuntu 14.10 下运行进程实时监控pidstat命令详解
    Ubuntu 14.10 下CPU实时监控mpstat命令详解
    Ubuntu 14.10 下awk命令详解
    Ubuntu 14.10 下sort,uniq,cut,wc命令详解
    Ubuntu 14.10 下sed命令详解
    Ubuntu 14.10 下grep命令详解
    Ubuntu 14.10 下Ganglia监控Spark集群
  • 原文地址:https://www.cnblogs.com/Dup4/p/10446403.html
Copyright © 2020-2023  润新知