test-35 solutions hackerrank solutions

1)
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>

unsigned long max_sum(
    unsigned long *partial_sums,
    unsigned long *dest,
    unsigned length,
    unsigned long target
) {
    if (length < 2)
        return (*dest = *partial_sums);

    unsigned
        lower_len = length >> 1,
        upper_len = length - lower_len;

    unsigned long
        lower[lower_len],
        upper[upper_len],
        max_left = max_sum(partial_sums, lower, lower_len, target),
        max_right = max_sum(&partial_sums[lower_len], upper, upper_len, target),
        max = max_left > max_right ? max_left : max_right;

    unsigned lesser = 0, greater = 0;

    while (lesser < lower_len && greater < upper_len)
        if (upper[greater] < lower[lesser]) {
            *dest = upper[greater++];
            unsigned long other_max = (*dest++ - lower[lesser]) + target;
            if (other_max > max)
                max = other_max;
        } else
            *dest++ = lower[lesser++];

    memcpy(dest, &lower[lesser], (lower_len - lesser) * sizeof(*dest));
    memcpy(&dest[lower_len - lesser], &upper[greater], (upper_len - greater) * sizeof(*dest));

    return max;
}

int main() {
    unsigned length;
    unsigned long test_case, limit, index;
    static unsigned long
        items[100000],
        buffer[100001] = {[0] = 0},
        *partial_sums = &buffer[1];

    for (scanf("%lu", &test_case); test_case--; ) {
        scanf("%u", &length);
        scanf("%lu", &limit);

        for (index = 0; index < length; index++) {
            scanf("%lu", &items[index]);
            items[index] %= limit;
            partial_sums[index] = (items[index] + partial_sums[index - 1ULL]) % limit;
        }

        // n log n, using partial sums w/ merge sort
        // either the max is in the lower, upper, or some where in between.
        //  find the max of each half,
        //  using sorted order check if the middle max is greater.
        static unsigned long ordered[100000];
        unsigned long max = max_sum(partial_sums, ordered, length, limit);

        // n^2 using partial sums ...
        //unsigned long max = partial_sums[0], chunk, sum, i, j;
        //for (i = 0; i < length; i++)
        //    for (j = i; j < length; j++) {
        //        sum = partial_sums[j] - partial_sums[i - 1];
        //        if (sum > limit) // overflow ...
        //            sum += limit;
        //        if (sum > max)
        //            max = sum;
        //    }

        // brute-force n^3, take max(sum of all possible lengths)
        //unsigned long max = items[0] % limit, chunk;
        //for (index = 1; index < length; index++)
        //    for (chunk = 0; chunk < length/index; chunk++) {
        //        unsigned long total = 0, start;
        //        for (start = chunk * index; start < index; total += items[start++]) ;

        //        total %= limit;
        //        if (total > max)
        //            max = total;
        //    }

        printf("%lu\n", max);

    }

    return 0;
}


2)
 IN C++



#include "bits/stdc++.h"
using namespace std;
#define rep(i,n) for(int (i)=0;(i)<(int)(n);++(i))
#define rer(i,l,u) for(int (i)=(int)(l);(i)<=(int)(u);++(i))
#define reu(i,l,u) for(int (i)=(int)(l);(i)<(int)(u);++(i))
static const int INF = 0x3f3f3f3f; static const long long INFL = 0x3f3f3f3f3f3f3f3fLL;
typedef vector<int> vi; typedef pair<int, int> pii; typedef vector<pair<int, int> > vpii; typedef long long ll;
template<typename T, typename U> static void amin(T &x, U y) { if (y < x) x = y; }
template<typename T, typename U> static void amax(T &x, U y) { if (x < y) x = y; }

struct MaxVal {
 long long val;
 MaxVal() : val(-INFL) {}
 explicit MaxVal(long long val) : val(val) {}
 MaxVal &operator+=(MaxVal that) {
  amax(val, that.val);
  return *this;
 }
 MaxVal operator+(MaxVal that) const {
  return MaxVal(*this) += that;
 }
};
using Val = long long;
using Sum = MaxVal;

//template<typename Val, typename Sum>
struct GetRangeRangeTree2D {
 typedef int Pos;
 vector<vector<int> > perms;
 vector<Pos> poses;
 vector<vector<Sum> > nodes;
 vector<vector<int> > rcnts;
 int n, log2n;
 void init(const vector<Pos> &ys, const Val &v = Val()) {
  init(ys, vector<Val>(ys.size(), v));
 }
private:
 struct IndirectPosCmp {
  const vector<Pos> &ys;
  IndirectPosCmp(const vector<Pos> &ys_) : ys(ys_) { }
  bool operator()(int i, int j) const {
   bool a = i >= (int)ys.size(), b = j >= (int)ys.size();
   if (a || b) return !a < !b;
   else return ys[i] < ys[j];
  }
 };
public:
 void init(const vector<Pos> &ys, const vector<Val> &vals) {
  n = 1, log2n = 0; while (n < (int)ys.size()) n *= 2, log2n ++;
  nodes.resize(n * 2);

  perms.assign(log2n + 1, vector<int>(n));
  nodes.assign(log2n + 1, vector<Sum>(n * 2));
  rcnts.assign(log2n, vector<int>(n + 1));

  vector<int> prev(n), cnt(n);
  for (int i = 0; i < n; i ++) {
   perms[log2n][i] = i;
   nodes[log2n][n + i] = i < (int)ys.size() ? Sum(vals[i]) : Sum();
   cnt[i] = i;
  }
  for (int i = n - 1; i > 0; -- i)
   nodes[log2n][i] = nodes[log2n][i * 2] + nodes[log2n][i * 2 + 1];

  vector<bool> origin(n);
  for (int k = log2n - 1; k >= 0; -- k) {
   prev.swap(cnt);
   int h = 1 << (log2n - k), h2 = (h - 1) / 2 + 1;
   vector<int> &cperms = perms[k];
   vector<Sum> &cnodes = nodes[k];
   vector<int> &crcnts = rcnts[k];
   for (int j = 0; j < n; j += h) {
    for (int k = 0; k < h; ++ k)
     origin[prev[j + k]] = k >= h / 2;
    merge(prev.begin() + j, prev.begin() + j + h / 2
     , prev.begin() + j + h / 2, prev.begin() + j + h
     , cnt.begin() + j, IndirectPosCmp(ys));
    for (int i = 0; i < h; i ++) {
     int p = cnt[j + i];
     cperms[p] = j + i;
     cnodes[j * 2 + h + i] = p < (int)ys.size() ? Sum(vals[p]) : Sum();
     crcnts[j + i + 1] = crcnts[j + i] + (origin[p] ? 1 : 0);
    }
    for (int i = h - 1; i > 0; -- i)
     cnodes[j * 2 + i] = cnodes[j * 2 + i * 2] + cnodes[j * 2 + i * 2 + 1];
   }
  }
  poses.resize(n);
  for (int i = 0; i < n; ++ i)
   poses[perms[0][i]] = i < (int)ys.size() ? ys[i] : -1;
 }
 Sum getRange(int i1, int j1, Pos i2, Pos j2) const {
  if (i1 >= j1 || i2 >= j2) return Sum();
  int pL = (int)(lower_bound(poses.begin(), poses.end(), i2) - poses.begin());
  int pR = (int)(lower_bound(poses.begin() + pL, poses.end(), j2) - poses.begin());
  return getRangeRec(0, 1, 0, i1, j1, i2, j2, pL, pR);
 }
 void set(int p, const Val &x) {
  for (int i = p + n, k = log2n; i > 0; i >>= 1, -- k) {
   int h = 1 << (log2n - k), base = (i - (1 << k)) * h;
   set1(&nodes[k][base * 2], h, perms[k][p] - base, x);
  }
 }
private:
 inline void set1(Sum *cnodes, int h, int i, const Val &x) const {
  cnodes[h + i] = Sum(x);
  for (i = (i + h) >> 1; i > 0; i >>= 1)
   cnodes[i] = sum1(cnodes, h, i * 2) + sum1(cnodes, h, i * 2 + 1);
 }
 Sum getRangeRec(int k, int i, int l, int i1, int j1, Pos i2, Pos j2, int pL, int pR) const {
  if (pL >= pR) return Sum();
  int h = 1 << (log2n - k);
  int base = (i - (1 << k)) * h;
  if (j1 - i1 == h) {
   return getRange1(&nodes[k][base * 2], h, pL, pR);
  } else {
   int m = l + h / 2;
   int qL = rcnts[k][base + pL] - rcnts[k][base];
   int qR = rcnts[k][base + pR] - rcnts[k][base];
   Sum res = Sum();
   if (i1 < m)
    res += getRangeRec(k + 1, i * 2, l, i1, min(j1, m), i2, j2, pL - qL, pR - qR);
   if (m < j1)
    res += getRangeRec(k + 1, i * 2 + 1, m, max(i1, m), j1, i2, j2, qL, qR);
   return res;
  }
 }
 inline Sum getRange1(const Sum *cnodes, int h, int i, int j) const {
  Sum res = Sum();
  for (int l = i + h, r = j + h; l < r; l >>= 1, r >>= 1) {
   if (l & 1) res += sum1(cnodes, h, l ++);
   if (r & 1) res += sum1(cnodes, h, -- r);
  }
  return res;
 }
 inline Sum sum1(const Sum *cnodes, int h, int i) const {
  return cnodes[i];
 }
};


struct City {
 int lat, lon, hei, pts;
};

int main() {
 int n; int xDiff; int yDiff;
 while (~scanf("%d%d%d", &n, &xDiff, &yDiff)) {
  vector<City> cities(n);
  rep(i, n) {
   int A; int B; int C; int D;
   scanf("%d%d%d%d", &A, &B, &C, &D);
   cities[i] = { A, B, C, D };
  }
  sort(cities.begin(), cities.end(), [](City a, City b) {
   return a.hei < b.hei;
  });
  vector<pair<int, int>> xis(n);
  rep(i, n)
   xis[i] = { cities[i].lat, i };
  sort(xis.begin(), xis.end());
  vector<int> ys(n);
  rep(i, n)
   ys[i] = cities[xis[i].second].lon;
  vector<long long> values(n);
  GetRangeRangeTree2D rt;
  rt.init(ys, -INFL);
  for (int iL = 0, iR = 0; iL != n; ) {
   for (; iR != n && cities[iR].hei == cities[iL].hei; ++ iR) {
    const City &c = cities[iR];
    int xL = (int)(lower_bound(xis.begin(), xis.end(), make_pair(c.lat - xDiff, -INF)) - xis.begin());
    int xR = (int)(upper_bound(xis.begin(), xis.end(), make_pair(c.lat + xDiff,  INF)) - xis.begin());
    int yL = c.lon - yDiff, yR = c.lon + yDiff + 1;
    MaxVal sum = rt.getRange(xL, xR, yL, yR);
    values[iR] = max(0LL, sum.val) + c.pts;
   }
   for (; iL != iR; ++ iL) {
    const City &c = cities[iL];
    int xi = (int)(lower_bound(xis.begin(), xis.end(), make_pair(c.lat, iL)) - xis.begin());
    rt.set(xi, values[iL]);
   }
  }
  long long ans = 0;
  rep(i, n)
   amax(ans, values[i]);
  printf("%lld\n", ans);
 }
 return 0;
}

Comments :

Post a Comment