QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#320997#7563. Fun on TreebobbilykingWA 4ms28628kbC++177.9kb2024-02-04 01:52:252024-02-04 01:52:25

Judging History

你现在查看的是最新测评结果

  • [2024-02-04 01:52:25]
  • 评测
  • 测评结果:WA
  • 用时:4ms
  • 内存:28628kb
  • [2024-02-04 01:52:25]
  • 提交

answer

// wrong code, saving the normal centroid decomp code somewhere 
//Centroid Decomposition
#pragma GCC target("avx2")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;

typedef long long int ll;
typedef long double ld;
typedef pair<ll, ll> pl;
typedef vector<ll> vl;

#define G(x) ll x; cin >> x;
#define F(i, l, r) for(ll i = l; i < (r); ++i)
const int N = 200010;

#define FD(i, l, r) for (ll i = l; i > (r); --i)
#define K first
#define V second
#define GS(s) string s; cin >> s;
#define A(a) begin(a), end(a)

vector<pl> tree[N];
ll sz[N], cPar[N], lvl[N]; //lvl is 1-indexed

#define L 20
ll dep[N], par[N][L], distFromRoot[N];
ll tin[N], tout[N];
void dfs(ll i, ll p, ll pw) {
    static int time = 0;
    dep[i] = dep[p] + 1;
    par[i][0] = p;
    distFromRoot[i] = pw;
    tin[i] = time++;
    F(l, 1, L) {
        par[i][l] = par[par[i][l - 1]][l - 1];
    }
    for(auto [j, w]: tree[i]) if(j - p) dfs(j, i, pw + w);
    tout[i] = time;
}

ll lca(ll a, ll b) {
    if(dep[a] < dep[b]) swap(a, b);
    FD(l, L - 1, -1) if((dep[a] - dep[b]) >> l) a = par[a][l];
    if(a == b) return a;
    FD(l, L - 1, -1) if(par[a][l] - par[b][l]) a = par[a][l], b = par[b][l];
    return par[a][0];
}

ll dist(ll a, ll b){
    return distFromRoot[a] + distFromRoot[b] - 2 * distFromRoot[lca(a, b)];
}

typedef pl T;

    typedef ll U;
// combining segtree nodes a and b
    
pl f(pl a, pl b) {
    if (a.K == b.K) return min(a, b);    
    return max(a, b); 
}

 // applying updates a and b (in that order)
    U g(U b, U a) { return a + b; }
    // applying update b to segtree node a
    T h(U b, T a) { 
        a.K += b;
        return a;
     }

struct lztree {

    ll n;

    T idT = {-1e18, -1};
    vector<T> t;
    U idU = 0;
    vector<U> d;

   

    void calc(ll p) { t[p] = h(d[p], f(t[p * 2], t[p * 2 + 1])); }

    void apply(ll p, U v) {
        t[p] = h(v, t[p]);
        if(p < n) d[p] = g(v, d[p]);
    }

    void push(ll p) {
        p += n;
        FD(s, L, 0) {
            ll i = p >> s;
            if(d[i] != idU) {
                apply(i * 2, d[i]);
                apply(i * 2 + 1, d[i]);
                d[i] = idU;
            }
        }
    }
    #define rein(p) lower_bound(A(mytins), p) - mytins.begin()

    // difference between tshi: i reindexx before doing shit 
    // void modify(ll p, T v) {
    //     p = rein(p);
    //     push(p);
    //     t[p += n] = v;
    //     while(p > 1) calc(p /= 2);
    // }

    void modify(ll l, ll r, U v) {
        l = rein(l), r = rein(r);

        if (l >= r) return;

        push(l), push(r - 1);
        bool cl = false, cr = false;
        for(l += n, r += n; l < r; l /= 2, r /= 2) {
            if(cl) calc(l - 1);
            if(cr) calc(r);
            if(l & 1) apply(l++, v), cl = true;
            if(r & 1) apply(--r, v), cr = true;
        }
        for(--l; r; l /= 2, r /= 2) {
            if(cl) calc(l);
            if(cr) calc(r);
        }
    }

    T query(ll l, ll r) {
        l = rein(l), r = rein(r);

                if (l >= r) return idT;


        push(l), push(r - 1);
        T resl = idT, resr = idT;
        for(l += n, r += n; l < r; l /= 2, r /= 2) {
            if(l & 1) resl = f(resl, t[l++]);
            if(r & 1) resr = f(t[--r], resr);
        }
        return f(resl, resr);
    }

    lztree() {}
    // This lazy tree wants to effectively query tin/tout ranges.
    // So reindex everything by tin; it is the responsibility of the passer to pass in correct tin/tout ranges.
    // (point modifies pass in tin ranges)

    vl mytins;
    lztree(vector<pl> pts) {
        assert(pts.size());
        n = pts.size();
        mytins.resize(n);
        t.resize(2*n, idT);
        d.resize(n, idU);
        F(i, 0, pts.size()) {
            mytins[i] = tin[pts[i].K];
            t[i+n] = pl(pts[i].V, pts[i].K);
        }
        FD(i, n-1, -1) t[i] = f(t[i*2], t[i*2+1]);
    }
};




struct distance_set {
    // segtree of nodes, sorted by tin time
    // this allows us to to range adds, range queries

    // ll pointupd(ll node, ll x) {
    //     seg.modify(tin[node], x);
    // }

    void rangeupd(ll node, ll x) {
        // cout << "FUCK " << node << " " << tin[node] << " " << tout[node] << endl;
        seg.modify(tin[node], tout[node], x);
        // add x to everybody's tin, tout time.
    }    

    pl query(ll node = -1) {
        if (node == -1); {
            // cout << "WTF " << tin[1] << " " << tout[1] << endl;
            // for (auto x: seg.mytins) cout << x << " "; cout << endl;
            return seg.query(tin[1], tout[1]);
        }
        // else, exclude node's tin, tout from the answer. 
        return max(seg.query(tin[1], tin[node]), seg.query(tout[node], tout[1]));
    }

    distance_set() {}

    lztree seg;

    distance_set(vector<pl> things) : seg(things) {
        
    }
};

distance_set children[N]; 

ll getSize(ll i, ll p) {
    sz[i] = 1;
    for(auto [j, _] : tree[i])
        if(j - p && !lvl[j])
            sz[i] += getSize(j, i);
    return sz[i];
}

ll centroid(ll i, ll p, ll n) {
    for(auto [j, _] : tree[i])
        if(j - p && !lvl[j] && sz[j] > n / 2)
            return centroid(j, i, n);
    return i;
}
ll a[N];

void dfsToGetThings(vector<pl>& things, ll i, ll p, ll dist) {
    things.emplace_back(i, dist - a[i]);
    
    for (auto [j, x] : tree[i]) if (j-p && !lvl[j]) {
        dfsToGetThings(things, j, i, x + dist);
    }
}


ll decomp(ll i, ll l) {
    vector<pl> things;
    dfsToGetThings(things, i, -1, 0);
    sort(A(things), [&](auto &a, auto &b) {
        return tin[a.K] < tin[b.K];
    });
        assert(things.size());

    // cout << "WTF??? " << things.size() << endl;

    ll cent = centroid(i, -1, getSize(i, -1));

    children[cent] = distance_set(things);

    // cout << "FILLED UP" << i << "; " << cent << endl;

    things.clear();
    
    lvl[cent] = l;
    for(auto [j, _]: tree[cent]) if(!lvl[j]) 
        cPar[decomp(j, l + 1)] = cent;
    return cent;
}


int main() {
    //    freopen("newbarn.in", "r", stdin);
    //    freopen("newbarn.out", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    G(n) G(q)

    F(i, 1, n+1) cin >> a[i];

    F(i, 2, n+1) {
        G(x) G(y) tree[x].emplace_back(i, y);
        tree[i].emplace_back(x, y);
    }
    dfs(1, 1, 0);
    auto root = decomp(1, 0);
    cPar[root] = 0;
    // cout << "ROOT " << root << endl;

    F(i, 1, n+1) cout << i << ": " << cPar[i] << endl;
    F(i, 1, n+1) assert(children[i].seg.n);

    // cout << "LOL? " << endl;

    while (q--) {
        G(x) G(y) G(w)

        // recursively updating is easy
        // cout << " rec update " << endl;
        {
            // Updating is wrong, we need to update all of its children's centroids too.. FUCKKK
            // ll root = y;
            // while (y) {
            //     // cout << "UDPATING " << y << " " << root << " " << w << endl;
            //     children[y].rangeupd(root, -w);
            //     // cout << "DONE UPD " << endl;
            //     y = cPar[y];
            // } 

            F(i, 1, n+1) children[i].rangeupd(y, -w);
        }

        // cout << " do query idot " << endl;

        assert(children[x].seg.n);
        auto base = children[x].query();

        cout << base.K << " ; " << base.V << endl;
        assert(base.V != -1);

        {
            ll root = x;
            ll income = x;
            x = cPar[x];
            while (x) {
                base = f(base, h(dist(x, root), children[x].query(income)));
                income = x;
                x = cPar[x];
            } 
        }
        cout << base.V << " " << base.K << endl;

        // cout << recrusivelyQuery(x, ) 
    }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Wrong Answer
time: 4ms
memory: 28628kb

input:

6 6
1 1 4 5 1 4
1 5
2 0
3 2
4 1
5 6
3 2 -100000
1 2 100000
1 1 0
2 2 66
3 1 5
4 4 -3

output:

1: 2
2: 3
3: 0
4: 5
5: 3
6: 5
100005 ; 6
6 100005
-1 ; 1
6 10
-1 ; 1
6 10
4 ; 1
1 4
-1 ; 1
1 -1
-73 ; 4
1 1

result:

wrong answer 1st lines differ - expected: '6 100005', found: '1: 2'