제출 #533658

#제출 시각아이디문제언어결과실행 시간메모리
533658rumen_mAliens (IOI16_aliens)C++17
100 / 100
127 ms8700 KiB
#include<iostream>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;

#define ll long long
#define MAXN 1000001
#define pb push_back
#define INFI (~(1LL<<63))
#define sq(x) ((x) * (x))
#define DELTA 0.000001

struct range{
 ll s, e;
 friend bool operator < (const range &a, const range &b) {
  if (a.s == b.s)
   return (a.e > b.e) ? true : false;
  else
   return (a.s < b.s) ? true : false;
  }
};


struct point {
 ll x, y;
};

struct line {
 ll m, c;
};

struct hull_line {
 ll m, c;
 ll k;
};

class Hull {
private:
 int cur, len;
 hull_line *L;
 double getx(ll m1, ll c1, ll m2, ll c2);

public:
 void addline(ll m, ll c, ll k);
 pair<ll,ll> getmin(ll x);
 void resetline();
 Hull();
 ~Hull();
};

Hull::Hull() {
 L = (hull_line*)malloc(MAXN * sizeof(hull_line));
}

Hull::~Hull() {
 free(L);
}

double Hull::getx(ll m1, ll c1, ll m2, ll c2) {
 return (c2-c1) / (double)(m1-m2);
}

void Hull::addline(ll m, ll c, ll k) {
 while (len >= 2) {
  double a = getx(m, c, L[len-1].m, L[len-1].c);
  double b = getx(m, c, L[len-2].m, L[len-2].c);
  if (a > b) break;
  len--;
 }
 L[len].m = m;
 L[len].c = c;
 L[len].k = k;
 len++;
}

pair<ll,ll> Hull::getmin(ll x) {
 if (cur >= len) cur = len-1;
 while (cur < len-1) {
  double a = getx(L[cur].m, L[cur].c, L[cur+1].m, L[cur+1].c);
  if (x > a)
   cur++;
  else
   break;
   // in case x==a first such line is considered
   // It can be proven using convex property
   // that k increase as cur increases
 }
 return make_pair(L[cur].m * x + L[cur].c, L[cur].k);
}

void Hull::resetline() {
 len = 0;
 cur = 0;
}


pair<ll,ll> hull(vector<range> &r, ll C, Hull &h) {
 int n = r.size();
 ll m, c;
 ll t, lastRes = 0LL, lastK = 0LL;
 h.resetline();
 pair<ll,ll> res;
 for (int i=0; i<n; ++i) {
  m = -2LL * (r[i].s - 1LL);
  c = lastRes + sq(r[i].s - 1LL);
  if (i > 0) {
   t = max(0LL, r[i-1].e - r[i].s + 1LL);
   c -= sq(t);
  }
  h.addline(m, c, lastK);
  res = h.getmin(r[i].e);
  lastRes = sq(r[i].e) + C + res.first;
  lastK = res.second + 1LL;
 }
 return make_pair(lastRes, lastK);;
}

ll find(vector<range> &r, int K, int M) {
 Hull h;
 int N = r.size();
 K = min(K, N);
 ll kl=1LL, kr=(ll)N, cl = sq((ll)M), cr=0LL;
 ll med;
 bool found = false;
 pair<ll,ll> res;
 if (cl % 2LL == 1LL) cl++; // keep C left to an even integer
 // run binary search on C=[cl,cr]
 while (kr-kl > 1LL && cl - cr > 1LL) {
  med = cr + (cl-cr)/2LL;
  // if (med % 2LL == 1LL) med--; // keep med even
  res = hull(r, med + 1LL, h);
  if (K == res.second) {
   found = true;
   break;
  }
  if (K < res.second) {
   cr = med;
   kr = res.second;
  } else {
   cl = med;
   kl = res.second;
  }
 }
 if (found) {
  return res.first - (med+1LL) * K;
 } else if (kr - kl > 1) {
  // slope is equal from kl to kr.
  // Since odd C values are used in hull() it always returns
  // leftmost k out of those slopes for given C. i.e. slopes are always even
  res = hull(r, cl+1LL, h);
  ll fl = res.first - (cl + 1LL) * kl;
  res = hull(r, cr+1LL, h);
  ll fr = res.first - (cr + 1LL) * kr;
  ll h = (fl-fr) / (kr - kl); // interpolate
  return fl - (K - kl) * h;
 } else {
  if (kr == K) {
   res = hull(r, cr + 1LL, h);
   return res.first - (cr + 1LL) * K;
  } else { //kr = K
   res = hull(r, cl + 1LL, h);
   return res.first - (cl + 1LL) * kl;
  }
 }
}

vector<range> parseRanges(range* r, int n) {
 sort(&r[0], &r[n]);
 vector<range> res;
 int cur = 0;
 res.pb(r[0]);
 for (int i=1; i<n; ++i)
  if (r[cur].e < r[i].s || r[cur].e < r[i].e) {
   cur = i;
   res.pb(r[i]);
  }
 return res;
}

long long take_photos(int n, int m, int k, vector<int> row, vector<int> col) {
 point *p = (point*)malloc(MAXN * sizeof(point));
 range *r = (range*)malloc(MAXN * sizeof(range));
 for (int i=0; i<n; ++i) {
  r[i].s = min(row[i], col[i]);
  r[i].e = max(row[i], col[i]);
 }
 vector<range> R = parseRanges(r, n);
 ll res = find(R, k, m);

 // do the same for other diagonal
 // for (int i=0; i<n; ++i) {
 //  r[i].s = min(p[i].y,m-p[i].x-1);
 //  r[i].e = max(p[i].y,m-p[i].x-1);
 // }
 // R = parseRanges(r, n);
 //res = min(res, find(R, k, m));
 return res;
}

// BEGIN CUT
/*
int main() {
    int n, m, k;
    scanf("%d %d %d", &n, &m, &k);
    std::vector<int> r(n), c(n);
    for (int i = 0; i < n; i++) {
        scanf("%d %d", &r[i], &c[i]);
    }
    long long ans = take_photos(n, m, k, r, c);

    // BEGIN SECRET
    puts("098d134608c94f7413faac591054ee35");
    // END SECRET

    printf("%lld\n", ans);
    return 0;
}
*/
// END CUT

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

aliens.cpp: In function 'long long int take_photos(int, int, int, std::vector<int>, std::vector<int>)':
aliens.cpp:182:9: warning: unused variable 'p' [-Wunused-variable]
  182 |  point *p = (point*)malloc(MAXN * sizeof(point));
      |         ^
#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...