답안 #592030

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
592030 2022-07-08T11:55:59 Z lorenzoferrari 사탕 분배 (IOI21_candies) C++17
11 / 100
156 ms 16796 KB
#include "candies.h"
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
using vi = vector<int>;

const LL Nan = 1e18;

struct Segment {
  struct node {
    LL mn;
    LL mx;
    LL lSum;
    LL lSet;
    node(LL x = 0) : mn(x), mx(x), lSum(0), lSet(Nan) {}
    node(LL x, LL y) : mn(x), mx(y), lSum(0), lSet(Nan) {}
  };
  node join(const node& a, const node& b) {
    return node(min(a.mn, b.mn), max(a.mx, b.mx));
  }
  int n;
  vector<node> t;
  Segment(int _n) {
    for (n = 1; n < _n; n <<= 1);
    t.resize(2 * n);
  }
  void applySum(int i, LL x) {
    if (t[i].lSet != Nan) {
      t[i].lSet += x;
    } else {
      t[i].lSum += x;
    }
  }
  void applySet(int i, LL x) {
    t[i].lSum = 0;
    t[i].lSet = x;
  }
  void prop(int i) {
    // you never want both lSum and lSet set
    if (t[i].lSum) {
      t[i].mn += t[i].lSum;
      t[i].mx += t[i].lSum;
      if (i < n) {
        applySum(2*i  , t[i].lSum);
        applySum(2*i+1, t[i].lSum);
      }
      t[i].lSum = 0;
    } else if (t[i].lSet != Nan) {
      t[i].mn = t[i].mx = t[i].lSet;
      if (i < n) {
        applySet(2*i  , t[i].lSet);
        applySet(2*i+1, t[i].lSet);
      }
      t[i].lSet = Nan;
    }
  }
  void add(int i, int l, int r, int a, int b, LL x) {
    prop(i);
    if (r <= a || b <= l) return;
    if (l <= a && b <= r) applySum(i, x);
    else {
      int m = (a+b) / 2;
      add(2*i  , l, r, a, m, x);
      add(2*i+1, l, r, m, b, x);
      t[i] = join(t[2*i], t[2*i+1]);
    }
  }
  void setmax(int i, int l, int r, int a, int b, LL x) {
    prop(i);
    if (r <= a || b <= l || t[i].mx <= x) return;
    if (l <= a && b <= r && t[i].mx == t[i].mn) {
      applySet(i, x);
    } else {
      int m = (a+b) / 2;
      setmax(2*i  , l, r, a, m, x);
      setmax(2*i+1, l, r, m, b, x);
      t[i] = join(t[2*i], t[2*i+1]);
    }
  }
  void setmin(int i, int l, int r, int a, int b, LL x) {
    prop(i);
    if (r <= a || b <= l || t[i].mn >= x) return;
    if (l <= a && b <= r && t[i].mx == t[i].mn) {
      applySet(i, x);
    } else {
      int m = (a+b) / 2;
      setmin(2*i  , l, r, a, m, x);
      setmin(2*i+1, l, r, m, b, x);
      t[i] = join(t[2*i], t[2*i+1]);
    }
  }
  void add(int l, int r, LL x) { add(1, l, r+1, 0, n, x); }
  void setmax(int l, int r, LL x) { setmax(1, l, r+1, 0, n, x); }
  void setmin(int l, int r, LL x) { setmin(1, l, r+1, 0, n, x); }
  int get(int p) {
    vector<int> a;
    for (int i = p + n; i > 0; i >>= 1) a.push_back(i);
    for (int i = int(a.size())-1; i >= 0; --i) prop(i);
    assert(t[p+n].mn == t[p+n].mx);
    return t[p+n].mn;
  }
};

vi c_equal(vi c, vi l, vi r, vi v) {
  int n = c.size();
  Segment st(n);
  for (int i = 0; i < int(l.size()); ++i) {
    st.add(l[i], r[i], v[i]);
    if (v[i] > 0) st.setmax(l[i], r[i], c[0]);
    else st.setmin(l[i], r[i], 0);
  }
  vector<int> s(n);
  for (int i = 0; i < n; ++i) {
    s[i] = st.get(i);
  }
  return s;
}

vi brute_force(vi c, vi l, vi r, vi v) {
  int n = c.size();
  vector<int> s(n, 0);
  for (int i = 0; i < int(l.size()); ++i) {
    for (int j = l[i]; j <= r[i]; ++j) {
      if (v[i] > 0) s[j] = min(s[j] + v[i], c[j]);
      if (v[i] < 0) s[j] = max(s[j] + v[i], 0);
    }
  }
  return s;
}

vi v_positive(vi c, vi l, vi r, vi v) {
  int n = c.size();
  vector<LL> prf(n+1);
  for (int i = 0; i < int(l.size()); ++i) {
    prf[l[i]] += v[i];
    prf[r[i] + 1] -= v[i];
  }
  for (int i = 1; i < n; ++i) {
    prf[i] += prf[i - 1];
  }
  vector<int> s(n);
  for (int i = 0; i < n; ++i) {
    s[i] = min((LL)c[i], prf[i]);
  }
  return s;
}

vi distribute_candies(vi c, vi l, vi r, vi v) {
  int n = c.size();
  int q = l.size();
  if (n <= 2000 && q <= 2000) {
    return brute_force(c, l, r, v);
  } else if (*min_element(v.begin(), v.end()) > 0) {
    return v_positive(c, l, r, v);
  } else if (*min_element(c.begin(), c.end()) == *max_element(c.begin(), c.end())) {
    return c_equal(c, l, r, v);
  }
  return vector<int>(n, 0);
}
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 2 ms 312 KB Output is correct
4 Correct 1 ms 340 KB Output is correct
5 Correct 4 ms 340 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 105 ms 16796 KB Output is correct
2 Correct 93 ms 16084 KB Output is correct
3 Correct 104 ms 15904 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Incorrect 156 ms 10516 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 212 KB Output is correct
2 Correct 1 ms 212 KB Output is correct
3 Incorrect 49 ms 7648 KB Output isn't correct
4 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
3 Correct 2 ms 312 KB Output is correct
4 Correct 1 ms 340 KB Output is correct
5 Correct 4 ms 340 KB Output is correct
6 Correct 105 ms 16796 KB Output is correct
7 Correct 93 ms 16084 KB Output is correct
8 Correct 104 ms 15904 KB Output is correct
9 Correct 1 ms 212 KB Output is correct
10 Incorrect 156 ms 10516 KB Output isn't correct
11 Halted 0 ms 0 KB -