UCSD ICPC Club Nov20 D

Since it’s guaranteed that each queried $v$ exists, this problem is not necessarily online.
First construct the entire tree, and then DP on the tree.
For each vertex, maintain two values, $minv$ and $maxv$, representing the minimum and maximum sums of the substring of the path from the root to this vertex.
Transition function:
$dpmax[i] = max(x, dpmax[v] + x)$
$dpmin[i] = min(x, dpmin[v] + x)$
Time complexity $O(n)$

Actually, this problem is a easy version, where the queries do not have to start from the root; they can be between any two vertices.
If it’s between any two vertices, first construct the entire tree, with each vertex storing the timestamp it was added and its weight.
Preprocess three arrays:
ancestor[i][j] represents the $2^j-th$ ancestor of vertex $i$
maxv[i][j] represents the maximum value of the path from vertex $i$ to its $2^j-th$ ancestor
minv[i][j] represents the minimum value of the path from vertex $i$ to its $2^j-th$ ancestor
Then preprocess the DP array. For each query, increase both vertex upwards by powers of two to find the answer. The complexity is $O(n\log)$.

For the harder version, another approach is heavy-light decomposition, with a complexity of $O(n\log^2)$. If require online, Link-Cut Tree is a solution.

// compile: make data
// run: ./data < data.in
#include <bits/stdc++.h>
using namespace std;
#pragma GCC optimize("O3,unroll-loops")
#ifdef LOCAL
#include <debug/codeforces.h>
#define debug(x...) _debug_print(#x, x);
#define Debug(x...) _debug_print_format(#x, x);
std::ifstream terminal("/dev/tty");
#define PP cerr<<"\033[1;30mpause...\e[0m",terminal.ignore();
#else
#define debug(x...)
#define Debug(x...)
#define PP
#endif
template<typename...Args> void print_(Args...args){((cout<<args<<" "),...)<<endl;}
#define rep(i,a,b) for(int i=(a);i<(int)(b);++i)
#define sz(v) ((int)(v).size())
#define print(...) print_(__VA_ARGS__);
#define FIND(a, x) ((find(a.begin(),a.end(),(x))!=a.end())?1:0)
#define cmin(x,...) x=min({(x),__VA_ARGS__})
#define cmax(x,...) x=max({(x),__VA_ARGS__})
#define INTMAX (int)(9223372036854775807)
#define INF (int)(1152921504606846976)
#define NaN (int)(0x8b88e1d0595d51d1)
#define double long double
#define int long long
#define uint unsigned long long
#define MAXN 200010

void solve() {
    int q; cin >> q;
    int idx = 0;
    // min, max
    vector<pair<int, int>> dp(q + 10, {INF, -INF}), num(q + 10);
    dp[idx] = {1, 1};
    num[idx] = {0, 1};
    while (q--) {
        string s; cin >> s;
        if (s[0] == '+') {
            int v, x; cin >> v >> x; --v;
            dp[++idx] = {min(x, dp[v].first + x), max(x, dp[v].second + x)};
            num[idx] = {min(num[v].first, dp[idx].first), max(num[v].second, dp[idx].second)};
            // debug(v, x, dp[idx], num[idx])
        }
        else if (s[0] == '?') {
            int u, v, x; cin >> u >> v >> x; --u, --v;
            cout << (x >= num[v].first && x <= num[v].second ? "YES" : "NO") << endl;
        }
    }
}

int32_t main() {
    ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);

    int _; cin >> _;
    while (_--) solve();

    return 0;
}
No Comments

Send Comment Edit Comment


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
Previous
Next