nickel2halide

N lg N planting

Dec 10th, 2012
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.18 KB | None | 0 0
  1. #include <fstream>
  2. #include <iostream>
  3.  
  4. #include <map>
  5. #include <vector>
  6. #include <algorithm>
  7.  
  8. using namespace std;
  9.  
  10. typedef long long ll;
  11.  
  12. ifstream fin("planting.in");
  13. ofstream fout("planting.out");
  14.  
  15. struct inter {
  16.     ll x, y1, y2;
  17.     int d;
  18.     inter(ll x, ll y1, ll y2, int d) : x(x), y1(y1), y2(y2), d(d) {}
  19.     bool operator<(const inter& o) const {
  20.         return x < o.x || (x == o.x && d > o.d);
  21.     }
  22. };
  23.  
  24. struct Node {
  25.     int lo, hi;
  26.     const vector<ll>& ys;
  27.  
  28.     Node *left;
  29.     Node *right;
  30.     int ct; // number of intervals [x, y) that contain [lo, hi) completely
  31.     ll len; // measure of union of interval parts in [lo, hi) range
  32.  
  33.     int disj; // number if disjoint interval parts in [lo, hi) range
  34.     bool abutl, abutr; // whether any interval abuts lo (or hi) side
  35.  
  36.     Node(int lo, int hi, const vector<ll>& ys) :
  37.       lo(lo), hi(hi), ys(ys), left(0), right(0), ct(0), len(0),
  38.       disj(0), abutl(false), abutr(false) {
  39.         if (hi -  lo > 1) left = new Node(lo, (lo + hi) / 2, ys),
  40.                           right = new Node((lo + hi) / 2, hi, ys);
  41.     }
  42.  
  43.     // update (d is always just +1 or -1 in this program)
  44.     void u(int l, int r, int d) {
  45.         if (r <= lo || hi <= l) return;
  46.         if (l <= lo && hi <= r) ct += d;
  47.         else if (left) left->u(l, r, d), right->u(l, r, d);
  48.         if (ct > 0) len = ys[hi] - ys[lo];
  49.         else len = left ? (left->len + right->len) : 0;
  50.         abutl = ct > 0 || (left && left->abutl);
  51.         abutr = ct > 0 || (left && right->abutr);
  52.         if (ct > 0) disj = 1;
  53.         else disj = left ? (left->disj + right->disj - (left->abutr && right->abutl)) : 0;
  54.     }
  55.  
  56.     // measure (length of union)
  57.     ll m() const {
  58.         return len;
  59.     }
  60.  
  61.     // # of disjoint intervals in union
  62.     int i() const {
  63.         return disj;
  64.     }
  65. };
  66.  
  67. int main() {
  68.     int N;
  69.     fin >> N;
  70.  
  71.     vector<inter> ntr;
  72.     vector<ll> ys;
  73.     map<ll, int> yid;
  74.     for (int i = 0; i < N; ++i) {
  75.         ll x1, y1, x2, y2;
  76.         fin >> x1 >> y1 >> x2 >> y2;
  77.         ntr.push_back(inter(x1, y2, y1, 1)), ntr.push_back(inter(x2, y2, y1, -1));
  78.         ys.push_back(y1), ys.push_back(y2);
  79.     }
  80.     sort(ntr.begin(), ntr.end());
  81.     sort(ys.begin(), ys.end()), unique(ys.begin(), ys.end());
  82.     for (int i = 0; i < ys.size(); ++i) yid[ys[i]] = i;
  83.     // just compressing the space of coordinates a bit
  84.  
  85.     ll area = 0, perim = 0;
  86.     Node* seg = new Node(0, ys.size() - 1, ys);
  87.     for (int i = 0, j = 0; i < 2 * N; i = j) {
  88.         while (j < 2 * N && ntr[j].x == ntr[i].x && ntr[j].d > 0)
  89.             seg->u(yid[ntr[j].y1], yid[ntr[j].y2], ntr[j].d), ++j;
  90.  
  91.         if (i == 0) perim += seg->m();
  92.         else {
  93.             ll total = seg->m();
  94.             while (j < 2 * N && ntr[j].x == ntr[i].x)
  95.                 seg->u(yid[ntr[j].y1], yid[ntr[j].y2], ntr[j].d), ++j;
  96.             perim += total - seg->m();
  97.         }
  98.  
  99.         if (j == 2 * N) break;
  100.  
  101.         ll w = ntr[j].x - ntr[i].x;
  102.         perim += 2 * seg->i() * w;
  103.         area += seg->m() * w;
  104.     }
  105.  
  106.     fout << area << "\n";
  107.  
  108.     cout << "Area: " << area << "\n";
  109.     cout << "Perimeter: " << perim << "\n";
  110.  
  111.     return 0;
  112. }
Advertisement
Add Comment
Please, Sign In to add comment