Submission #1215605

#TimeUsernameProblemLanguageResultExecution timeMemory
1215605vaneaTree (IOI24_tree)C++20
0 / 100
2097 ms62044 KiB
#include <bits/stdc++.h>
#include "tree.h"
using namespace std;
using ll = long long;

const int mxN = 2e5+10;

vector<int> adj[mxN];
ll w[mxN], st[4*mxN], lazy[4*mxN], st1[mxN*4], lazy1[mxN*4];
int tin[mxN], tout[mxN], timer = -1, n;
set<array<int, 2>> mn[mxN];
ll ans = 0, l, r;

void build(int node, int l, int r) {
    if(l == r) {
        st[node] = 0; lazy[node] = 0; st1[node] = 0;
        return ;
    }
    int mid = (l+r)/2;
    build(node*2, l, mid);
    build(node*2+1, mid+1, r);
}

void dfs(int node, int p) {
    tin[node] = ++timer;
    for(auto it : adj[node]) {
        if(it == p) continue;
        dfs(it, node);
    }
    tout[node] = timer;
}

void push(int node, int l, int r, int flag) {
    if(l == r) return ;
    if(flag == 0) {
        lazy[node*2] += lazy[node];
        lazy[node*2+1] += lazy[node];
        st[node*2] += lazy[node];
        st[node*2+1] += lazy[node];
        lazy[node] = 0;
    }
    else {
        lazy1[node*2] += lazy1[node];
        lazy1[node*2+1] += lazy1[node];
        st1[node*2] += lazy1[node];
        st1[node*2+1] += lazy1[node];
        lazy1[node] = 0;
    }
}

int qry1(int node, int l, int r, int l1, int r1) {
    push(node, l, r, 1);
    if(l1 <= l && r <= r1) return st1[node];
    if(l1 > r || r1 < l) return 0;
    int mid = (l+r)/2;
    return qry1(node*2, l, mid, l1, r1) + qry1(node*2+1, mid+1, r, l1, r1);
}

int qry(int node, int l, int r, int l1, int r1) {
    push(node, l, r, 0);
    if(l1 <= l && r <= r1) return st[node];
    if(l1 > r || r1 < l) return 0;
    int mid = (l+r)/2;
    return qry(node*2, l, mid, l1, r1) + qry(node*2+1, mid+1, r, l1, r1);
}

void upd1(int node, int l, int r, int l1, int r1, int x) {
    push(node, l, r, 1);
    if(l1 <= l && r <= r1) {
        st1[node] += x;
        lazy1[node] += x;
        return ;
    }
    if(l1 > r || r1 < l) return ;
    int mid = (l+r)/2;
    upd1(node*2, l, mid, l1, r1, x);
    upd1(node*2+1, mid+1, r, l1, r1, x);
    st1[node] = st1[node*2] + st1[node*2+1];
}

void upd(int node, int l, int r, int l1, int r1, int x) {
    push(node, l, r, 0);
    if(l1 <= l && r <= r1) {
        st[node] += x;
        lazy[node] += x;
        return ;
    }
    if(l1 > r || r1 < l) return ;
    int mid = (l+r)/2;
    upd(node*2, l, mid, l1, r1, x);
    upd(node*2+1, mid+1, r, l1, r1, x);
    st[node] = st[node*2] + st[node*2+1];
}


void dfs1(int node, int p) {
    if(adj[node].size() == 0) {
        ans += w[node] * l;
        upd(1, 0, timer+1, tin[node], tin[node], l);
        return ;
    }
    mn[node].insert({w[node], node});
    for(auto it : adj[node]) {
        if(it == p) continue;
        dfs1(it, node);
        if(mn[it].size() > mn[node].size()) swap(mn[it], mn[node]);
        for(auto it1 : mn[it]) {
            mn[node].insert(it1);
        }
        mn[it].clear();
    }
    int cnt = qry(1, 0, timer+1, tin[node], tout[node]);
    while(cnt > r) {
        array<int, 2> now = *(mn[node].begin());
        int del = qry1(1, 0, timer+1, tin[now[1]], tin[now[1]]);
        if(del > 0) {
            mn[node].erase(mn[node].begin());
            continue;
        }
        int k = qry(1, 0, timer+1, tin[now[1]], tout[now[1]]);
        int mx = k-l;
        int needed = cnt-r;
        if(mx >= needed) {
            cnt = r;
            ans += now[0] * needed;
            upd(1, 0, timer+1, tin[now[1]], tin[now[1]], -needed);
        }
        else {
            cnt -= mx;
            ans += now[0] * mx;
            upd(1, 0, timer+1, tin[now[1]], tin[now[1]], -mx);
            upd1(1, 0, timer+1, tin[now[1]], tout[now[1]], 1);
            mn[node].erase(mn[node].begin());
        }
    }
}

void init(vector<int> P, vector<int> W) {
    n = P.size();
    for(int i = 0; i < n; i++) w[i] = W[i];
    for(int i = 1; i < n; i++) {
        adj[P[i]].push_back(i);
    }
    dfs(0, -1);
}

ll query(int L, int R) {
    ans = 0; l = L; r = R;
    for(int i = 0; i < n; i++) {
        mn[i].clear();
    }
    build(1, 0, timer+1);
    dfs1(0, -1);
    return ans;
}

/*int main()
{
    //init({-1, 0, 0}, {1, 1, 1});
    init({-1, 0, 0, 1, 1, 1, 2, 2, 2}, {2, 3, 1, 4, 4, 3, 3, 3, 1});
    cout << query(1, 1) << ' ' << query(1, 2) << ' ' << query(3, 5);
    cout << ' ' << query(5, 10);
}*/

Compilation message (stderr)

tree.cpp: In function 'void dfs1(int, int)':
tree.cpp:102:28: warning: narrowing conversion of 'w[node]' from 'll' {aka 'long long int'} to 'int' [-Wnarrowing]
  102 |     mn[node].insert({w[node], node});
      |                      ~~~~~~^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...