제출 #1334972

#제출 시각아이디문제언어결과실행 시간메모리
1334972SmuggingSpunJobs (BOI24_jobs)C++20
100 / 100
568 ms56332 KiB
#include<bits/stdc++.h>
#define taskname "A"
using namespace std;
typedef long long ll;
template<class T>void maximize(T& a, T b){
  if(a < b){
    a = b;
  }
}
const int lim = 3e5 + 5;
int n, x[lim], p[lim];
ll money;
namespace sub1{
  void solve(){
    vector<vector<int>>g(n + 1);
    for(int i = 1; i <= n; i++){
      g[p[i]].push_back(i);
    }
    x[0] = 0;
    function<ll(int)>dfs;
    dfs = [&] (int s){
      ll sum = 0;
      for(int& d : g[s]){
        sum += dfs(d);
      }
      return max(0LL, sum + x[s]);
    };
    cout << dfs(0);
  }
}
namespace sub2{
  bool check_subtask(){
    if(n > 2000){
      return false;
    }
    for(int i = 1; i <= n; i++){
      if(p[i] != 0 && p[i] != i - 1){
        return false;
      }
    }
    return true;
  }
  struct Data{
    int start, end;
    ll need, profit;
    Data(){}
    Data(int _start, int _end, ll _need, ll _profit) : start(_start), end(_end), need(_need), profit(_profit) {}
    friend bool operator <(const Data a, const Data b){
      return a.need > b.need || (a.need == b.need && a.profit < b.profit);
    } 
  };
  void solve(){
    priority_queue<Data>pq;
    vector<bool>ban_start(n + 1, false);
    vector<int>left(n + 1);
    p[n + 1] = 0;
    for(int i = 1; i <= n; i++){
      left[i] = p[i] == 0 ? i : left[i - 1];
      if(p[i + 1] == 0){
        ll need = 0, profit = 0;
        for(int j = left[i]; j <= i; j++){
          maximize(need, -(profit += x[j]));
          if(profit > 0){
            pq.push(Data(left[i], j, need, profit));
          }
        }
      }
    }
    ll init_money = money;
    while(!pq.empty()){
      auto [start, end, need, profit] = pq.top();
      pq.pop();
      if(ban_start[start]){
        continue;
      }
      if(need > money){
        break;
      }
      money += profit;
      ban_start[start] = true;
      need = profit = 0;
      for(int i = end + 1; i <= n && left[i] == left[start]; i++){
        maximize(need, -(profit += x[i]));
        if(profit > 0){
          pq.push(Data(end + 1, i, need, profit));
        }     
      }
    }
    cout << money - init_money;
  }
}
namespace sub3{
  bool check_subtask(){
    for(int i = 1; i <= n; i++){
      if(p[i] != 0 && p[i] != i - 1){
        return false;
      }
    }
    return true;
  }
  struct Node{
    ll pmin, pmax, sum;
    Node(){
      pmin = pmax = sum = 0;
    }
  };
  int left[lim];
  Node st[lim << 2];
  Node merge(Node a, Node b){
    Node c;
    c.pmin = min(a.pmin, a.sum + b.pmin);
    c.pmax = max(a.pmax, a.sum + b.pmax);
    c.sum = a.sum + b.sum;
    return c;    
  }
  void build(int id, int l, int r){
    if(l == r){
      st[id].pmin = min(0LL, st[id].sum = x[l]);
      st[id].pmax = max(0, x[l]);
      return;
    }
    int m = (l + r) >> 1;
    build(id << 1, l, m);
    build(id << 1 | 1, m + 1, r);
    st[id] = merge(st[id << 1], st[id << 1 | 1]);
  }
  Node get(int id, int l, int r, int u, int v){
    if(l > v || r < u){
      return Node();
    }
    if(u <= l && v >= r){
      return st[id];
    }
    int m = (l + r) >> 1;
    return merge(get(id << 1, l, m, u, v), get(id << 1 | 1, m + 1, r, u, v));
  }
  struct Data{
    int start, end;
    ll need, profit;
    Data(){}
    Data(int _start, int _end, ll _need, ll _profit) : start(_start), end(_end), need(_need), profit(_profit) {}
    friend bool operator <(const Data a, const Data b){
      return a.need > b.need || (a.need == b.need && a.profit < b.profit);
    } 
  };
  priority_queue<Data>pq;
  void find_and_push(int i){
    int low = i, high = n, end = -1;
    Node ans;
    while(low <= high){
      int mid = (low + high) >> 1;
      if(left[mid] != left[i]){
        high = mid - 1;
      }
      else{
        Node x = get(1, 1, n, i, mid);
        if(x.pmax < 1){
          low = mid + 1;
        }
        else{
          ans = x;
          high = (end = mid) - 1;
        }
      }
    }
    if(end != -1){
      pq.push(Data(i, end, -ans.pmin, ans.pmax));
    }
  }
  void solve(){
    build(1, 1, n);
    for(int i = 1; i <= n; i++){
      left[i] = p[i] == 0 ? i : left[i - 1];
    }
    for(int i = 1; i <= n; i++){
      if(p[i] == 0){
        find_and_push(i);
      }
    }
    ll init_money = money;
    while(!pq.empty()){
      auto [start, end, need, profit] = pq.top();
      pq.pop();
      if(need > money){
        break;
      }
      money += profit;
      if(end < n && left[end + 1] == left[start]){
        find_and_push(end + 1);
      }
    }
    cout << money - init_money;
  }
}
namespace sub45{
  int lab[lim];
  ll profit[lim], need[lim];
  int find_set(int i){
    while(i != lab[i]){
      i = lab[i] = lab[lab[i]];
    }
    return i;
  }
  void solve(){
    profit[lab[0] = 0] = money;
    for(int i = 1; i <= n; i++){
      need[lab[i] = i] = min(0LL, profit[i] = x[i]); 
    }
    priority_queue<pair<ll, int>>pq;
    for(int i = 1; i <= n; i++){
      if(x[i] > 0){
        pq.push(make_pair(need[i], i));
      }
    }
    while(!pq.empty()){
      auto [foo, i] = pq.top();
      pq.pop();
      if(i == find_set(i)){
        int j = find_set(lab[i] = p[i]);
        ll new_need = min(need[j], profit[j] + need[i]);
        if(new_need < 0 && j == 0){
          break;
        }
        profit[j] += profit[i];
        need[j] = new_need;
        if(j > 0 && profit[j] > 0){
          pq.push(make_pair(need[j], j));
        }
      }
    }
    cout << profit[0] - money;
  }
}
int main(){
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	if(fopen(taskname".inp", "r")){
		freopen(taskname".inp", "r", stdin);
	}
  cin >> n >> money;
  for(int i = 1; i <= n; i++){
    cin >> x[i] >> p[i];
  }
  if(money == ll(1e18)){
    sub1::solve();
  }
  else if(sub2::check_subtask()){
    sub2::solve();
  }
  else if(sub3::check_subtask()){
    sub3::solve();
  }
  else{
    sub45::solve();
  }
}

컴파일 시 표준 에러 (stderr) 메시지

Main.cpp: In function 'int main()':
Main.cpp:237:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  237 |                 freopen(taskname".inp", "r", stdin);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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...