結果

問題 No.2311 [Cherry 5th Tune] Cherry Month
ユーザー 👑 NachiaNachia
提出日時 2023-05-20 19:26:06
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 562 ms / 4,600 ms
コード長 20,770 bytes
コンパイル時間 2,245 ms
コンパイル使用メモリ 125,880 KB
実行使用メモリ 83,544 KB
最終ジャッジ日時 2024-06-01 07:27:00
合計ジャッジ時間 24,509 ms
ジャッジサーバーID
(参考情報)
judge5 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 3 ms
5,248 KB
testcase_02 AC 417 ms
48,828 KB
testcase_03 AC 126 ms
16,344 KB
testcase_04 AC 140 ms
19,624 KB
testcase_05 AC 148 ms
20,392 KB
testcase_06 AC 210 ms
24,016 KB
testcase_07 AC 128 ms
14,552 KB
testcase_08 AC 247 ms
38,032 KB
testcase_09 AC 215 ms
29,468 KB
testcase_10 AC 251 ms
33,040 KB
testcase_11 AC 216 ms
33,804 KB
testcase_12 AC 293 ms
35,316 KB
testcase_13 AC 252 ms
32,056 KB
testcase_14 AC 327 ms
43,040 KB
testcase_15 AC 323 ms
38,604 KB
testcase_16 AC 251 ms
24,492 KB
testcase_17 AC 365 ms
45,512 KB
testcase_18 AC 317 ms
43,840 KB
testcase_19 AC 313 ms
39,760 KB
testcase_20 AC 251 ms
31,364 KB
testcase_21 AC 249 ms
26,340 KB
testcase_22 AC 221 ms
28,888 KB
testcase_23 AC 279 ms
34,244 KB
testcase_24 AC 241 ms
31,868 KB
testcase_25 AC 262 ms
37,328 KB
testcase_26 AC 287 ms
39,044 KB
testcase_27 AC 302 ms
54,884 KB
testcase_28 AC 303 ms
55,200 KB
testcase_29 AC 282 ms
55,024 KB
testcase_30 AC 243 ms
46,060 KB
testcase_31 AC 238 ms
46,056 KB
testcase_32 AC 241 ms
46,192 KB
testcase_33 AC 311 ms
59,416 KB
testcase_34 AC 356 ms
58,124 KB
testcase_35 AC 345 ms
59,004 KB
testcase_36 AC 393 ms
57,368 KB
testcase_37 AC 412 ms
57,272 KB
testcase_38 AC 425 ms
57,104 KB
testcase_39 AC 438 ms
62,572 KB
testcase_40 AC 422 ms
62,988 KB
testcase_41 AC 433 ms
63,256 KB
testcase_42 AC 376 ms
59,344 KB
testcase_43 AC 426 ms
65,088 KB
testcase_44 AC 456 ms
82,752 KB
testcase_45 AC 451 ms
82,316 KB
testcase_46 AC 285 ms
38,304 KB
testcase_47 AC 447 ms
83,544 KB
testcase_48 AC 333 ms
62,740 KB
testcase_49 AC 349 ms
62,736 KB
testcase_50 AC 562 ms
62,704 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#line 1 "..\\Main.cpp"

#line 2 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\set\\merger-forest.hpp"
#include <vector>
#include <algorithm>
#line 4 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\set\\dsu-fast.hpp"

namespace nachia {

struct DsuFast{
private:
    std::vector<int> w;
public:
    DsuFast(int n = 0) : w(n, -1) {}
    int leader(int u){
        if(w[u] < 0) return u;
        return w[u] = leader(w[u]);
    }
    int operator[](int u){ return leader(u); }
    int merge(int u, int v){
        u = leader(u);
        v = leader(v);
        if(u == v) return u;
        if(-w[u] < -w[v]) std::swap(u, v);
        w[u] += w[v];
        w[v] = u;
        return u;
    }
    int size(int u){ return -w[leader(u)]; }
    bool same(int u, int v){ return leader(u) == leader(v); }
};

} // namespace nachia
#line 3 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\graph\\graph.hpp"
#include <utility>
#include <cassert>
#line 5 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\array\\csr-array.hpp"

namespace nachia{

template<class Elem>
class CsrArray{
public:
    struct ListRange{
        using iterator = typename std::vector<Elem>::iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        Elem& operator[](int i) const { return begi[i]; }
    };
    struct ConstListRange{
        using iterator = typename std::vector<Elem>::const_iterator;
        iterator begi, endi;
        iterator begin() const { return begi; }
        iterator end() const { return endi; }
        int size() const { return (int)std::distance(begi, endi); }
        const Elem& operator[](int i) const { return begi[i]; }
    };
private:
    int m_n;
    std::vector<Elem> m_list;
    std::vector<int> m_pos;
public:
    CsrArray() : m_n(0), m_list(), m_pos() {}
    static CsrArray Construct(int n, std::vector<std::pair<int, Elem>> items){
        CsrArray res;
        res.m_n = n;
        std::vector<int> buf(n+1, 0);
        for(auto& [u,v] : items){ ++buf[u]; }
        for(int i=1; i<=n; i++) buf[i] += buf[i-1];
        res.m_list.resize(buf[n]);
        for(int i=(int)items.size()-1; i>=0; i--){
            res.m_list[--buf[items[i].first]] = std::move(items[i].second);
        }
        res.m_pos = std::move(buf);
        return res;
    }
    static CsrArray FromRaw(std::vector<Elem> list, std::vector<int> pos){
        CsrArray res;
        res.m_n = pos.size() - 1;
        res.m_list = std::move(list);
        res.m_pos = std::move(pos);
        return res;
    }
    ListRange operator[](int u) { return ListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    ConstListRange operator[](int u) const { return ConstListRange{ m_list.begin() + m_pos[u], m_list.begin() + m_pos[u+1] }; }
    int size() const { return m_n; }
    int fullSize() const { return (int)m_list.size(); }
};

} // namespace nachia
#line 6 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\graph\\graph.hpp"

namespace nachia{


struct Graph {
public:
    struct Edge{
        int from, to;
        void reverse(){ std::swap(from, to); }
    };
    using Base = std::vector<std::pair<int, int>>;
    Graph(int n = 0, bool undirected = false, int m = 0) : m_n(n), m_e(m), m_isUndir(undirected) {}
    Graph(int n, const std::vector<std::pair<int, int>>& edges, bool undirected = false) : m_n(n), m_isUndir(undirected){
        m_e.resize(edges.size());
        for(std::size_t i=0; i<edges.size(); i++) m_e[i] = { edges[i].first, edges[i].second };
    }
    template<class Cin>
    static Graph Input(Cin& cin, int n, bool undirected, int m, bool offset = 0){
        Graph res(n, undirected, m);
        for(int i=0; i<m; i++){
            int u, v; cin >> u >> v;
            res[i].from = u - offset;
            res[i].to = v - offset;
        }
        return res;
    }
    int numVertices() const noexcept { return m_n; }
    int numEdges() const noexcept { return int(m_e.size()); }
    int addNode() noexcept { return m_n++; }
    int addEdge(int from, int to){ m_e.push_back({ from, to }); return numEdges() - 1; }
    Edge& operator[](int ei) noexcept { return m_e[ei]; }
    const Edge& operator[](int ei) const noexcept { return m_e[ei]; }
    Edge& at(int ei) { return m_e.at(ei); }
    const Edge& at(int ei) const { return m_e.at(ei); }
    auto begin(){ return m_e.begin(); }
    auto end(){ return m_e.end(); }
    auto begin() const { return m_e.begin(); }
    auto end() const { return m_e.end(); }
    bool isUndirected() const noexcept { return m_isUndir; }
    void reverseEdges() noexcept { for(auto& e : m_e) e.reverse(); }
    void contract(int newV, const std::vector<int>& mapping){
        assert(numVertices() == int(mapping.size()));
        for(int i=0; i<numVertices(); i++) assert(0 <= mapping[i] && mapping[i] < newV);
        for(auto& e : m_e){ e.from = mapping[e.from]; e.to = mapping[e.to]; }
        m_n = newV;
    }
    std::vector<Graph> induce(int num, const std::vector<int>& mapping) const {
        int n = numVertices();
        assert(n == int(mapping.size()));
        for(int i=0; i<n; i++) assert(-1 <= mapping[i] && mapping[i] < num);
        std::vector<int> indexV(n), newV(num);
        for(int i=0; i<n; i++) if(mapping[i] >= 0) indexV[i] = newV[mapping[i]]++;
        std::vector<Graph> res; res.reserve(num);
        for(int i=0; i<num; i++) res.emplace_back(newV[i], isUndirected());
        for(auto e : m_e) if(mapping[e.from] == mapping[e.to] && mapping[e.to] >= 0) res[mapping[e.to]].addEdge(indexV[e.from], indexV[e.to]);
        return res;
    }
    CsrArray<int> getEdgeIndexArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(int i=0; i<numEdges(); i++){
            auto e = operator[](i);
            src.emplace_back(e.from, i);
            if(undirected) src.emplace_back(e.to, i);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getEdgeIndexArray() const { return getEdgeIndexArray(isUndirected()); }
    CsrArray<int> getAdjacencyArray(bool undirected) const {
        std::vector<std::pair<int, int>> src;
        src.reserve(numEdges() * (undirected ? 2 : 1));
        for(auto e : m_e){
            src.emplace_back(e.from, e.to);
            if(undirected) src.emplace_back(e.to, e.from);
        }
        return CsrArray<int>::Construct(numVertices(), src);
    }
    CsrArray<int> getAdjacencyArray() const { return getAdjacencyArray(isUndirected()); }
private:
    int m_n;
    std::vector<Edge> m_e;
    bool m_isUndir;
};

} // namespace nachia
#line 6 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\set\\merger-forest.hpp"

namespace nachia{

struct MergerForest{
private:
    int _n;
    int _m;
    std::vector<int> parent;
    int np = 0;
    
public:

    MergerForest(int n, const std::vector<std::pair<int,int>>& edges){
        _n = n;
        _m = edges.size();
        auto dsu = DsuFast(n);
        auto root = std::vector<int>(n);
        for(int i=0; i<n; i++) root[i] = i;
        np = n;
        parent.assign(_n + _m, -1);
        for(auto e : edges){
            int u = dsu.leader(e.first);
            int v = dsu.leader(e.second);
            parent[root[u]] = np;
            if(u != v) parent[root[v]] = np;
            if(u != v) u = dsu.merge(u, v);
            root[u] = np++;
        }
    }

    int numNodes() const noexcept { return np; }
    int parentOf(int v) const noexcept { return parent[v]; }

    Graph getForest(bool doAddRoot, bool undirected = false) const {
        Graph res(np + (doAddRoot ? 1 : 0), undirected);
        for(int i=0; i<np; i++){
            if(parentOf(i) >= 0){
                res.addEdge(parentOf(i), i);
            }
            else if(doAddRoot){
                res.addEdge(np, i);
            }
        }
        return res;
    }
};

} // namespace nachia
#line 6 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\tree\\heavy-light-decomposition.hpp"

namespace nachia{

struct HeavyLightDecomposition{
private:

    int N;
    std::vector<int> P;
    std::vector<int> PP;
    std::vector<int> PD;
    std::vector<int> D;
    std::vector<int> I;

    std::vector<int> rangeL;
    std::vector<int> rangeR;

public:

    HeavyLightDecomposition(const CsrArray<int>& E = CsrArray<int>::Construct(1, {}), int root = 0){
        N = E.size();
        P.assign(N, -1);
        I = {root};
        I.reserve(N);
        for(int i=0; i<(int)I.size(); i++){
            int p = I[i];
            for(int e : E[p]) if(P[p] != e){
                I.push_back(e);
                P[e] = p;
            }
        }
        std::vector<int> Z(N, 1);
        std::vector<int> nx(N, -1);
        PP.resize(N);
        for(int i=0; i<N; i++) PP[i] = i;
        for(int i=N-1; i>=1; i--){
            int p = I[i];
            Z[P[p]] += Z[p];
            if(nx[P[p]] == -1) nx[P[p]] = p;
            if(Z[nx[P[p]]] < Z[p]) nx[P[p]] = p;
        }

        for(int p : I) if(nx[p] != -1) PP[nx[p]] = p;

        PD.assign(N,N);
        PD[root] = 0;
        D.assign(N,0);
        for(int p : I) if(p != root){
            PP[p] = PP[PP[p]];
            PD[p] = std::min(PD[PP[p]], PD[P[p]]+1);
            D[p] = D[P[p]]+1;
        }
        
        rangeL.assign(N,0);
        rangeR.assign(N,0);
        
        for(int p : I){
            rangeR[p] = rangeL[p] + Z[p];
            int ir = rangeR[p];
            for(int e : E[p]) if(P[p] != e) if(e != nx[p]){
                rangeL[e] = (ir -= Z[e]);
            }
            if(nx[p] != -1){
                rangeL[nx[p]] = rangeL[p] + 1;
            }
        }

        I.resize(N);
        for(int i=0; i<N; i++) I[rangeL[i]] = i;
    }
    
    HeavyLightDecomposition(const Graph& tree, int root = 0)
        : HeavyLightDecomposition(tree.getAdjacencyArray(true), root) {}

    int numVertices() const { return N; }
    int depth(int p) const { return D[p]; }
    int toSeq(int vertex) const { return rangeL[vertex]; }
    int toVtx(int seqidx) const { return I[seqidx]; }
    int toSeq2In(int vertex) const { return rangeL[vertex] * 2 - D[vertex]; }
    int toSeq2Out(int vertex) const { return rangeR[vertex] * 2 - D[vertex] - 1; }
    int parentOf(int v) const { return P[v]; }
    int heavyRootOf(int v) const { return PP[v]; }
    int heavyChildOf(int v) const {
        if(toSeq(v) == N-1) return -1;
        int cand = toVtx(toSeq(v) + 1);
        if(PP[v] == PP[cand]) return cand;
        return -1;
    }

    int lca(int u, int v) const {
        if(PD[u] < PD[v]) std::swap(u, v);
        while(PD[u] > PD[v]) u = P[PP[u]];
        while(PP[u] != PP[v]){ u = P[PP[u]]; v = P[PP[v]]; }
        return (D[u] > D[v]) ? v : u;
    }

    int dist(int u, int v) const {
        return depth(u) + depth(v) - depth(lca(u,v)) * 2;
    }

    std::vector<std::pair<int,int>> path(int r, int c, bool include_root = true, bool reverse_path = false) const {
        if(PD[c] < PD[r]) return {};
        std::vector<std::pair<int,int>> res(PD[c]-PD[r]+1);
        for(int i=0; i<(int)res.size()-1; i++){
            res[i] = std::make_pair(rangeL[PP[c]], rangeL[c]+1);
            c = P[PP[c]];
        }
        if(PP[r] != PP[c] || D[r] > D[c]) return {};
        res.back() = std::make_pair(rangeL[r]+(include_root?0:1), rangeL[c]+1);
        if(res.back().first == res.back().second) res.pop_back();
        if(!reverse_path) std::reverse(res.begin(),res.end());
        else for(auto& a : res) a = std::make_pair(N - a.second, N - a.first);
        return res;
    }

    std::pair<int,int> subtree(int p){
        return std::make_pair(rangeL[p], rangeR[p]);
    }

    int median(int x, int y, int z) const {
        return lca(x,y) ^ lca(y,z) ^ lca(x,z);
    }

    int la(int from, int to, int d) const {
        if(d < 0) return -1;
        int g = lca(from,to);
        int dist0 = D[from] - D[g] * 2 + D[to];
        if(dist0 < d) return -1;
        int p = from;
        if(D[from] - D[g] < d){ p = to; d = dist0 - d; }
        while(D[p] - D[PP[p]] < d){
            d -= D[p] - D[PP[p]] + 1;
            p = P[PP[p]];
        }
        return I[rangeL[p] - d];
    }
};

} // namespace nachia
#line 2 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\array\\segment-tree.hpp"

#line 4 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\array\\segment-tree.hpp"

namespace nachia{

template<
    class S,
    S op(S l, S r)
>
struct SegmentTree {
private:
    int N;
    std::vector<S> A;

    void mergev(int i){
        if(i < N) A[i] = op(A[i*2], A[i*2+1]);
    }
public:
    SegmentTree(int n, S e){
        N = 1; while (N < n) N *= 2;
        A.assign(N * 2, e);
    }
    SegmentTree(const std::vector<S>& a, S e) : SegmentTree(a.size(), e){
        for(int i=0; i<(int)a.size(); i++) A[i + N] = a[i];
        for(int i=N-1; i>=1; i--) mergev(i);
    }

    void set(int p, S x){
        p += N; A[p] = x;
        for(int d=1; (1<<d)<=N; d++) mergev(p>>d);
    }

    S get(int p){ return A[N+p]; }

    S prod(int l, int r) const {
        l += N; r += N;
        S ql = A[0], qr = A[0];
        while(l<r){
            if(l&1) ql = op(ql, A[l++]);
            if(r&1) qr = op(A[--r], qr);
            l /= 2;
            r /= 2;
        }
        return op(ql, qr);
    }

    S allProd() const { return A[1]; }

    // bool cmp(S)
    template<class E>
    int minLeft(int r, E cmp, int a = 0, int b = 0, int i = -1){
        static S x;
        if(i == -1){ a=0; b=N; i=1; x=A[0]; }
        if(r <= a) return a;
        if(b <= r){
            S nx = op(A[i], x);
            if(cmp(nx)){ x = nx; return a; }
        }
        if(b - a == 1) return b;
        int q = minLeft(r, cmp, (a+b)/2, b, i*2+1);
        if(q > (a+b)/2) return q;
        return minLeft(r, cmp, a, (a+b)/2, i*2);
    }

    // bool cmp(S)
    template<class E>
    int maxRight(int l, E cmp, int a = 0, int b = 0, int i = -1){
        static S x;
        if(i == -1){ a=0; b=N; i=1; x=A[0]; }
        if(b <= l) return b;
        if(l <= a){
            S nx = op(x, A[i]);
            if(cmp(nx)){ x = nx; return b; }
        }
        if(b - a == 1) return a;
        int q = maxRight(l, cmp, a, (a+b)/2, i*2);
        if(q < (a+b)/2) return q;
        return maxRight(l, cmp, (a+b)/2, b, i*2+1);
    }
};

} // namespace nachia
#line 3 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\range-query\\point-set-range-min.hpp"
#include <functional>

namespace nachia {
    template<class T, class Cmp = std::less<T>>
    struct PointSetRangeMin{
    private:
        static T minop(T l, T r){ return std::min(l, r, Cmp()); }
        using Base = SegmentTree<T, minop>;
        Base base;
        Cmp cmpx;
    public:
        PointSetRangeMin() {}
        PointSetRangeMin(int len, T INF)
            : base(len, INF){}
        PointSetRangeMin(const std::vector<T>& init, T INF)
            : base(init, INF){}
        T min(int l, int r){ return base.prod(l, r); }
        T min(){ return base.allProd(); }
        void set(int pos, T val){ base.set(pos, val); }
        T get(int pos){ return base.get(pos); }
        int lBoundLeft(int from, T val){ return base.minLeft(from, [this,val](const T& x){ return cmpx(val, x); }); }
        int uBoundLeft(int from, T val){ return base.minLeft(from, [this,val](const T& x){ return !cmpx(x, val); }); }
        int lBoundRight(int from, T val){ return base.maxRight(from, [this,val](const T& x){ return cmpx(val, x); }); }
        int uBoundRight(int from, T val){ return base.maxRight(from, [this,val](const T& x){ return !cmpx(x, val); }); }
        template<class E>
        int minLeft(int r, E cmp){ return base.minLeft(r, cmp); }
        template<class E>
        int maxRight(int l, E cmp){ return base.maxRight(l, cmp); }
    };
} // namespace nachia
#line 4 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\array\\fenwicktree-atcoder.hpp"

namespace nachia {

template <class T> struct FenwickTree {
public:
    FenwickTree() : _n(0){}
    explicit FenwickTree(int n, T ZERO) : _n(n), a(n, ZERO){}
    void add(int p, T x){
        assert(0 <= p && p < _n);
        p++;
        while(p <= _n){
            a[p-1] += T(x);
            p += p & -p;
        }
    }
    T sum(int r){
        assert(0 <= r && r <= _n);
        return sumr(r);
    }
    T sum(int l, int r){
        assert(0 <= l && l <= r && r <= _n);
        return sumr(r) - sumr(l);
    }
private:
    int _n;
    std::vector<T> a;

    T sumr(int r){
        T s = 0;
        while(r > 0){
            s += a[r-1];
            r -= r & -r;
        }
        return s;
    }
};

}  // namespace nachia
#line 3 "D:\\Programming\\VSCode\\competitive-cpp\\nachia\\range-query\\point-add-range-sum.hpp"

namespace nachia {
    template<class T> using PointAddRangeSum = FenwickTree<T>;
} // namespace nachia
#line 6 "..\\Main.cpp"

#include <iostream>
#include <string>
#line 11 "..\\Main.cpp"
#include <atcoder/modint>
using namespace std;
using i32 = int;
using u32 = unsigned int;
using i64 = long long;
using u64 = unsigned long long;
#define rep(i,n) for(int i=0; i<(int)(n); i++)
const i64 INF = 1001001001001001001;

using Modint = atcoder::static_modint<998244353>;


int main(){
    int N; cin >> N;
    vector<i64> A(N);
    rep(i,N) cin >> A[i];
    
    int T; cin >> T;
    vector<pair<int,int>> edges;
    vector<vector<int>> events;
    rep(ti,T){
        int t, x, k; cin >> t >> x >> k;
        events.push_back({ t, x, k });
        if(t == 1) edges.push_back({ x-1, k-1 });
    }

    auto mergertree = nachia::MergerForest(N, edges);
    auto hld = nachia::HeavyLightDecomposition(mergertree.getForest(true, true), mergertree.numNodes());
    auto rmq = nachia::PointSetRangeMin<int, greater<int>>(hld.numVertices() * 2, -1001001);
    rep(v,hld.numVertices()){
        rmq.set(hld.toSeq2In(v), v);
        rmq.set(hld.toSeq2Out(v), hld.parentOf(v));
    }

    int Q; cin >> Q;
    struct Query {
        int t;
        int pos;
        int i;
    };
    vector<Query> queries(Q);
    rep(i,Q){
        cin >> queries[i].t >> queries[i].pos;
        queries[i].pos--;
        queries[i].i = i;
    }

    vector<i64> decrease_single(N);
    vector<i64> decrease_lazy(N);
    vector<int> edgecnt(N);
    vector<vector<int>> direct_edges(N);
    auto decrease_component = nachia::PointAddRangeSum<i64>(hld.numVertices() * 2 + 1, 0);

    for(auto& [u,v] : edges){ edgecnt[u]++; edgecnt[v]++; }
    for(auto& [u,v] : edges) if(edgecnt[u] > edgecnt[v]) swap(u, v);

    vector<i64> ans(Q);
    sort(queries.begin(), queries.end(), [](Query l, Query r){ return l.t < r.t; });
    int xtime = 0;
    int ecounted = 0;
    for(auto& q : queries){
        while(xtime < q.t){
            //cout << "xtime = " << xtime << endl;
            auto& e = events[xtime];
            int ty = e[0];
            if(ty == 1){
                //cout << "ty 1" << endl;
                auto edge = edges[ecounted];
                direct_edges[edge.first].push_back(edge.second);
                decrease_single[edge.first] -= decrease_lazy[edge.second];
                ecounted++;
            }
            if(ty == 2){
                //cout << "ty 2" << endl;
                decrease_single[e[1]-1] += e[2];
            }
            if(ty == 3){
                //cout << "ty 3" << endl;
                int v = e[1] - 1;
                decrease_single[v] += e[2];
                decrease_lazy[v] += e[2];
                for(int to : direct_edges[v]) decrease_single[to] += e[2];
            }
            if(ty == 4){
                //cout << "ty 4" << endl;
                int v = e[1] - 1;
                //cout << "ecounted = " << ecounted << endl;
                int lrq = rmq.lBoundLeft(hld.toSeq2In(v), N + ecounted);
                int rrq = rmq.lBoundRight(hld.toSeq2In(v), N + ecounted);
                //cout << "lrq = " << lrq << " , rrq = " << rrq << endl;
                decrease_component.add(lrq, e[2]);
                decrease_component.add(rrq, -e[2]);
            }
            //cout << "fin : xtime = " << xtime << endl;
            xtime++;
        }

        i64 dec_sum = 0;
        dec_sum += decrease_component.sum(0, hld.toSeq2In(q.pos) + 1);
        dec_sum += decrease_single[q.pos];
        for(int v : direct_edges[q.pos]) dec_sum += decrease_lazy[v];
        ans[q.i] = max((i64)0, A[q.pos] - dec_sum);
        //cout << "query" << endl;
    }
    
    rep(i,Q){
        cout << ans[i];
        cout << '\n';
    }
    return 0;
}



struct ios_do_not_sync{
    ios_do_not_sync(){
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    }
} ios_do_not_sync_instance;

0