看门人

Description

Yxuanwkeith 的家有一个很大的花园,我们可以把这个花园抽象成是一棵以 1 为根的,总共有 N 个节点的树。PHILIPS 为了赚钱,到了 Yxuanwkeith 的家中打杂工,更具体的,他当上了一个看门人。Yxuanwkeith的家这么大,看门人当然不是简单的站着就可以的了,要进行日常的巡逻活动。具体而言,对于花园中第 i 个节点,看门队长定下了两个参数,L i ,R i ,PHILIPS 每天,需要把经过 i 的,且不经过这个 i 到节点 1 路径上除 i 外所有点的,边数在 [L i ,R i ] 间的所有路径都走一遍。这当然是个很累的差事了,但 PHILIPS 很乐观,他觉得,只要走过的最长路径比较短,他就一点都不累。现在把花园的信息告诉你,你需要对于每个点,把PHILIPS 走过的最长路径的长度输出。假如不存在则输出 -1。 由于输出量较大,令 Ans i 为第 i 个节点对应的长度,只需要输出( ∑ Ni=1 23333N−i Ans i )mod 998244353,注意这里是算术取模,即最终答案的范围是 [0,998244353)。

Input

第一行一个整数 N。 接下来 N 行,第 i 行两个整数 L i ,R i 。 接下来 N − 1 行,第 i 行两个整数 u i ,c i ,表示节点 i + 1 到节点 1 的路径上经过的第一个点是 u i ,i + 1 到 u i 的距离是 c i 。

Output

一行一个整数,代表要求的答案。

Sample Input

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
7
2 5
1 1
1 3
1 1
1 1
1 1
1 3
5 4
1 4
7 2
4 1
4 2
3 5

Sample Output

1
339343281

HINT

第一个样例中,每个点的答案分别是:16,-1,9,2,4,-1,7。

Source

day2

Solution

线段树合并 打标记删除好题

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const LL INF = 1000000007ll * 1000000007ll;
const LL Mod = 998244353ll;
const int maxn = 1000002;
inline int getint() {
    int r = 0; bool b = true; char c = getchar();
    while ('0' > c || c > '9') { if (c == '-') b = false; c = getchar(); }
    while ('0' <= c && c <= '9') { r = r * 10 + (c - '0'); c = getchar(); }
    if (b) return r;
    return -r;
}
LL mx[maxn*4], dis[maxn], T[maxn], ans[maxn], ANS;
int n, ind[maxn*4], clo, dep[maxn], siz[maxn], h[maxn], cnte, son[maxn], L[maxn], R[maxn];
struct edge_T {int to,next; LL w;} edge[maxn];
inline void ins(int x, int y, LL z) {edge[++cnte].to=y;edge[cnte].next=h[x];edge[cnte].w=z;h[x]=cnte;}
void dfs(int now, int deep, LL distance) {
    dep[now] = deep;
    dis[now] = distance;
    siz[now] = 1;
    for (int i = h[now]; i; i = edge[i].next) {
        dfs(edge[i].to, deep+1, distance + edge[i].w);
        siz[now] += siz[edge[i].to];
        if (siz[edge[i].to] > siz[son[now]]) son[now] = edge[i].to;
    }
}
void change(int now, int l, int r, int pos, LL val) {
    if (ind[now] != clo) {ind[now] = clo; mx[now] = val;}
    else mx[now] = max(mx[now], val);
    if (l == r) return;
    else {
        int mid = (l + r) >> 1;
        if (pos <= mid) change(now << 1, l, mid, pos, val);
        else change(now << 1 | 1, mid + 1, r, pos, val);
    }
}
LL res;
void query(int now, int l, int r, int ll, int rr) {
    if (ind[now] != clo) return;
    if (mx[now] <= res) return;
    if (ll <= l && r <= rr) res = mx[now];
    else {
        int mid = (l + r) >> 1;
        if (ll <= mid) query(now << 1, l, mid, ll, rr);
        if (rr > mid) query(now << 1 | 1, mid + 1, r, ll, rr);
    }
}
inline LL QUERY(int l, int r) {res = -INF; query(1, 1, n, l, r); return res;}
void calc(int now, int rt) {
    for (int i = h[now]; i; i = edge[i].next) calc(edge[i].to, rt);
    int LL = max(1, dep[rt] + L[rt] + dep[rt] - dep[now]);
    int RR = min(n, dep[rt] + R[rt] + dep[rt] - dep[now]);
    if (LL <= RR) ans[rt] = max(ans[rt], QUERY(LL, RR) - dis[rt] + dis[now] - dis[rt]);
}
void merg(int now, int rt) {
    for (int i = h[now]; i; i = edge[i].next) merg(edge[i].to, rt);
    change(1, 1, n, dep[now], dis[now]);
}
void solve(int now) {
    ++clo;
    for (int i = h[now]; i; i = edge[i].next) if (edge[i].to != son[now]) solve(edge[i].to);
    if (son[now]) solve(son[now]);
    for (int i = h[now]; i; i = edge[i].next) if (edge[i].to != son[now]) {calc(edge[i].to, now); merg(edge[i].to, now);}
    int LL = max(1, dep[now] + L[now]);
    int RR = min(n, dep[now] + R[now]);
    if (LL <= RR) ans[now] = max(ans[now], QUERY(LL, RR) - dis[now]);
    change(1, 1, n, dep[now], dis[now]);
    ANS = (ANS + ans[now] % Mod * T[n - now] % Mod) % Mod;
}
int main() {
    freopen("watchdog.in", "r", stdin);
    freopen("watchdog.out", "w", stdout);
    int x;
    n = getint(); T[0] = 1ll;
    for (int i = 1; i <= n; ++i) {ans[i] = -1ll; L[i] = getint(); R[i] = getint(); T[i] = T[i-1] * 23333ll % Mod;}
    for (int i = 2; i <= n; ++i) {x = getint(); ins(x, i, getint());}
    dfs(1, 1, 0);
    solve(1);
    printf("%lld", ANS);
    fclose(stdin);
    fclose(stdout);
    return 0;
}