Submission #1270307

#TimeUsernameProblemLanguageResultExecution timeMemory
1270307strange420Souvenirs (IOI25_souvenirs)C++20
25 / 100
12 ms408 KiB
#include "souvenirs.h"
#include <utility>
#include <vector>
#include <iostream>

std::pair<std::vector<int>, long long> specialTransaction(long long M, std::vector<int> &cnt, std::vector<long long> &price);
void half(long long P0, int target, std::vector<int> &cnt, std::vector<long long> &price, std::vector<std::pair<std::vector<int>, long long>> &equations);

void subtask3(int N, long long P0) {
  // Subtask 3
  std::vector<int> cnt(N, 0);
  std::vector<int> price(N, 0);

  long long current_price = P0 - 1;
  while (price[N-1] == 0) {
    std::pair<std::vector<int>, long long> res = transaction(current_price);

    for (auto x: res.first) {
      cnt[x]++;
    }

    if (res.first.size() == 1 && res.second == 0) {
      int i = res.first[0];
      price[i] = current_price;
      current_price --;
    } else {
      int i = res.first[0];
      price[i] = current_price - 1;
      current_price -= 2;
    }
  }

  for (int i=1; i<N; i++) {
    for (int j = cnt[i]; j < i; j++) {
      transaction(price[i]);
    }
  }
}

void subtask5(int N, long long P0) {
  // Subtask 5
  std::vector<int> cnt(N, 0);
  std::vector<std::pair<std::vector<int>, long long>> equations;
  std::vector<long long> price(N+1, 0); price[0] = P0; price[N] = 1;
  half(P0, N-1, cnt, price, equations);

  for (int i=N-2; i>1; i--) {
    if (price[i]) continue;
    std::pair<std::vector<int>, long long> res = specialTransaction(2*price[i+1], cnt, price);

    if (res.first.size() == 1) {
      price[i] = price[i+1]*2 - res.second;
      continue;
    }

    int zeros = 0, ind = -1;
    long long part = 0;
    std::vector<int> asd;
    for (int x: res.first) {
      if (!price[x]) {
        zeros++;
        ind = x;
        asd.push_back(x);
      } else {
        part += price[x];
      }
    }

    if (zeros == 1) {
      price[ind] = price[i+1]*2 - (res.second + part);
    } else {
      equations.push_back(std::pair(asd, res.second - part));
    }
  }

  for (int i=0; i<N; i++) {
    while (cnt[i] < i) {
      transaction(price[i]);
      cnt[i]++;
    }
  }
}

std::pair<std::vector<int>, long long> specialTransaction(long long M, std::vector<int> &cnt, std::vector<long long> &price) {
  std::pair<std::vector<int>, long long> res = transaction(M);
  for (auto x: res.first) {
    cnt[x]++;
  }

  if (res.first.size() == 1) {
    price[res.first[0]] = M - res.second;
  }

  return res;
}

bool simplify(std::vector<std::pair<std::vector<int>, long long>> &equations, std::vector<long long> &price) {
  std::vector<std::pair<std::vector<int>, long long>> equations2;
  for (auto pp: equations) {
    if (pp.first.size() < 1) continue;
    if (pp.first.size() == 1) {
      price[pp.first[0]] = pp.second;
      continue;
    }

    int zeros = 0, ind = -1;
    long long part = 0;
    std::vector<int> asd;
    for (int x: pp.first) {
      if (!price[x]) {
        zeros++;
        ind = x;
        asd.push_back(x);
      } else {
        part += price[x];
      }
    }

    if (zeros == 1) {
      price[ind] = pp.second - part;
    } else {
      if (pp.second - part == 0) continue;
      equations2.push_back(std::pair(asd, pp.second - part));
    }
  }
  if (equations2.size() != equations.size()) {
    equations = equations2;
    return true;
  } else {
    for (int i=0; i<equations.size(); i++) {
      if (equations[i].second != equations2[i].second) {
        equations = equations2;
        return true;
      }
    }
    return false;
  }
}

void half(long long current_price, int target, std::vector<int> &cnt, std::vector<long long> &price, std::vector<std::pair<std::vector<int>, long long>> &equations) {
  while (price[target] == 0) {
    std::pair<std::vector<int>, long long> res = specialTransaction(current_price, cnt, price);

    std::vector<int> asd;
    long long part = res.second;
    for (int x: res.first) {
      if (price[x]) {
        part += price[x];
      } else {
        asd.push_back(x);
      }
    }

    if (asd.size() > 0) {
      equations.push_back(std::pair(asd, current_price - part));
    }

    if (!asd.size()) {
      int temp = res.first[0];
      for (int x: res.first) {
        if (x >= target) break;
        temp = x;
      }
      current_price = price[temp] - 1;
    } else {
      current_price = (current_price - part)/asd.size();
    }
    simplify(equations, price);
  }
}

void resolve_all(std::vector<std::pair<std::vector<int>, long long>> &equations, std::vector<long long> &price, std::vector<int> &cnt) {
  while(equations.size()) {
    while(true) {
      bool flag = false;
      simplify(equations, price);
      for (auto pp: equations) {
        for (int x: pp.first) {
          if (price[x]) {
            flag = true;
          }
        }
      }
      if (!flag) {
        break;
      }
    }
    std::vector<int> num = equations[0].first;
    long long sum = equations[0].second;
    half(sum/num.size(), num[num.size()-1], cnt, price, equations);
    simplify(equations, price);
  }
}

void subtask6(int N, long long P0) {
  // Subtask 6
  std::vector<int> cnt(N, 0);
  std::vector<std::pair<std::vector<int>, long long>> equations;
  std::vector<long long> price(N+1, 0); price[0] = P0; price[N] = 1;

  half(P0-1, N-1, cnt, price, equations);
  resolve_all(equations, price, cnt);

  for (int i=0; i<N; i++) {
    while (cnt[i] < i) {
      transaction(price[i]);
      cnt[i]++;
    }
  }
}

void buy_souvenirs(int N, long long P0) {
  if (N == 2) {
    // Subtask 1
    transaction(P0 - 1);
  } else if (P0 == N) {
    // Subtask 2
    for (long long i = N-1, k = 1; i>0; i--, k++) {
      for (int j = 0; j < k; j++) {
        transaction(i);
      }
    }
  } else if (N == 3) {
    // Subtask 4
    std::pair<std::vector<int>, long long> res = transaction(P0-1);
    long long price = P0-1-res.second;
    if (res.first.size() == 1) {
      transaction(price-1);
      transaction(price-1);
    } else {
      long long special = price / 2;
      transaction(special);
    }
  } else {
    subtask6(N, P0);
  }
}
#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...