# |
Submission time |
Handle |
Problem |
Language |
Result |
Execution time |
Memory |
998588 |
2024-06-14T09:44:57 Z |
vjudge1 |
Jobs (BOI24_jobs) |
C++17 |
|
2000 ms |
41372 KB |
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define int long long
const ll INF = 2e18;
vector<ll> orderedSum; //For binary search purposes, reduces constant significantly.
void updateDp(int v, vector<ll>& dp, vector<ll>& sum, vector<int>& x, vector<set<pair<ll, ll>>>& stack){
int lo = 0;
int hi = (int)orderedSum.size() - 1;
while(lo <= hi){
int mid = (lo + hi) / 2;
auto it = stack[v].upper_bound({orderedSum[mid], INF});
if(it == stack[v].begin()){
//I don't have any minPre so low in stack, so I can go higher.
lo = mid + 1;
continue;
}
it--;
ll mnPre = (*it).first;
ll mxPre = (*it).second;
// cout << "Mid "<< mid << " minPre " << mnPre << " maxPre "<< mxPre << "\n";
if(mxPre >= sum[v] - x[v]){
dp[v] = min(dp[v], -mnPre);
lo = mid + 1; //I can go higher, try for bigger minPre.
}else hi = mid - 1;
}
// cout << "dp "<< dp[v] << "\n";
// cout << "Ending v "<< v << " stack:\n";
// for(pair<ll, ll> p : stack[v]){
// cout << p.first << " " << p.second << "\n";
// }
}
void DFS(int v, vector<vector<int>>& adj, vector<ll>& dp, vector<int>& x, vector<ll>& sum, vector<set<pair<ll, ll>>>& stack){
for(int node : adj[v]){
DFS(node, adj, dp, x, sum, stack);
if((int)stack[node].size() > (int)stack[v].size()) swap(stack[node], stack[v]);
//I need to add first the oldest (i.e. with less prefix min.) to maintain the
//order of the the one I'm adding.
for(pair<ll, ll> pr : stack[node]){
ll maxPre = pr.second;
//Here, I should not erase prefix mins that are bigger then me, because
//they are parallel. I should only erase smaller prefix mins which smaller
//maxPre, because they are useless. This way, smaller prefix mins will
//always have bigger maxPre, and I can do binary search.
//I should also be careful to not add it if there is one with minPre
//>= me and also a maxPre >= me.
auto it = stack[v].lower_bound(pr);
if(it != stack[v].end() && (*it).second >= maxPre){
//Then I am useless, so I skip.
continue;
}
//Here I need to check if I can erase some.
it = stack[v].lower_bound(pr);
while(it != stack[v].begin()){
it--;
if((*it).second <= maxPre){
//Then it is useless, so I erase it.
stack[v].erase(it);
}else break;
it = stack[v].lower_bound(pr);
}
stack[v].insert(pr);
}
}
//Add me.
//When adding me, I need to erase 100% the ones with prefixMin > me.
//because that won't be possible anymore.
//Then, when only prefixMin <= me are left, I go from bigger to smaller and only
//erase the next one if it's useless, i.e., its prefixMax is <= than mine.
//Also careful, if there is one with prefixMin == me and its prefixMax is bigger than mine,
//I will not add myself.
// cout << "Initial v "<< v << " stack:\n";
// for(pair<ll, ll> p : stack[v]){
// cout << p.first << " " << p.second << "\n";
// }
ll minPre = sum[v];
ll maxPre = sum[v];
auto it = stack[v].lower_bound({minPre, INF}); //i.e they have p.first > minPre.
while(it != stack[v].end()){
maxPre = max(maxPre, (*it).second); //I update the maxPrefix.
stack[v].erase(it);
it = stack[v].lower_bound({minPre, INF});
}
if(stack[v].empty()){
stack[v].insert({minPre, maxPre});
//I need to update dp here.
updateDp(v, dp, sum, x, stack);
return;
}
pair<ll, ll> lst = *stack[v].rbegin();
if(lst.first == minPre && lst.second >= maxPre){
updateDp(v, dp, sum, x, stack);
//I'm useless.
return;
}
while(!stack[v].empty()){
auto it = stack[v].end(); it--;
if((*it).second <= maxPre) stack[v].erase(it);
}
stack[v].insert({minPre, maxPre});
//Now, I calculate the DP with binary search.
//I want the maximum minPre, so that -(minPre - (sum[v] - x[v])) is minimum,
//which is the cost, such that its maxPre is maxPre - (sum[v] - x[v]) is >= 0.
//which means that maxPre >= sum[v] - x[v].
updateDp(v, dp, sum, x, stack);
}
signed main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
int N; ll s; cin >> N >> s;
ll orgs = s;
vector<int> x(N), p(N);
vector<vector<int>> adj(N);
vector<ll> sum(N, 0);
for(int i = 0; i < N; i++){
cin >> x[i] >> p[i]; p[i]--;
if(p[i] != -1){
adj[p[i]].push_back(i);
sum[i] = sum[p[i]];
}
sum[i] += x[i];
}
orderedSum = sum;
sort(orderedSum.begin(), orderedSum.end());
vector<ll> dp(N, 2e18); //Min cost until profit.
vector<set<pair<ll, ll>>> stack(N);
for(int i = 0; i < N; i++){
if(p[i] == -1) DFS(i, adj, dp, x, sum, stack);
}
priority_queue<pair<ll, int>> q;
for(int i = 0; i < N; i++){
if(p[i] == -1){
q.push({-dp[i], i});
}
}
while(!q.empty() && -q.top().first <= s){
int v = q.top().second; q.pop();
s += x[v];
for(int node : adj[v]){
q.push({-dp[node], node});
}
}
cout << s - orgs << "\n";
}
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
2061 ms |
41372 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
2065 ms |
600 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
2065 ms |
600 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
2065 ms |
600 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |
# |
Verdict |
Execution time |
Memory |
Grader output |
1 |
Execution timed out |
2061 ms |
41372 KB |
Time limit exceeded |
2 |
Halted |
0 ms |
0 KB |
- |