Submission #762883

#TimeUsernameProblemLanguageResultExecution timeMemory
762883caganyanmazPairs (IOI07_pairs)C++17
82 / 100
3479 ms524288 KiB
#include <bits/stdc++.h> #define pb push_back using namespace std; struct SegTree1d { int n; vector<int> data, left, right; SegTree1d(int n) : n(n), data(1, 0), left(1, -1), right(1, -1) {} void cc(int index) { if (left[index] == -1) { left[index] = data.size(); data.pb(0); left.pb(-1); right.pb(-1); } if (right[index] == -1) { right[index] = data.size(); data.pb(0); left.pb(-1); right.pb(-1); } } void update(int l, int r, int index, int i, int val) { if (i >= r || l > i) return; if (l + 1 == r) { data[index] += val; return; } cc(index); int m = l+r>>1; update(l, m, left[index], i, val); update(m, r, right[index], i, val); data[index] = data[left[index]] + data[right[index]]; } int get(int l, int r, int index, int ss, int ee) { if (ss >= r || l >= ee) return 0; if (ee >= r && l >= ss) return data[index]; int m = l+r>>1; int lres = 0, rres = 0; if (left[index] != -1) lres = get(l, m, left[index], ss, ee); if (right[index] != -1) rres = get(m, r, right[index], ss, ee); return lres + rres; } void update(int i, int val) { update(0, n, 0, i, val ); } int get(int ss, int ee) { return get(0, n, 0, ss, ee); } }; void solve1d() { int n, d, m; cin >> n >> d >> m; SegTree1d st(m); vector<int> v(n); for (int& i : v) { cin >> i; i--; st.update(i, 1); } int64_t encounters = 0; for (int i : v) encounters += st.get(i-d, i+d+1) - 1; cout << (encounters / 2) << "\n"; } struct SegTree2d { int ll, rr, uu, dd; vector<int> data; vector<int> left, right; vector<int> root; vector<int> down, up; SegTree2d (int ll, int rr, int dd, int uu) : ll(ll), rr(rr), uu(uu), dd(dd), root(1, -1), up(1, -1), down(1, -1) {} int create_x() { int res = data.size(); data.pb(0); left.pb(-1); right.pb(-1); assert(res != -1); return res; } int create_y() { int res = root.size(); root.pb(-1); down.pb(-1); up.pb(-1); assert(res != -1); return res; } void update_row(int l, int r, int index, int x, int val) { if (l + 1 == r) { data[index] += val; return; } int m = l+r>>1; if (m > x) { if (left[index] == -1) { int tmp = create_x(); left[index] = tmp; } assert(left[index] != -1); update_row(l, m, left[index], x, val); } else { if (right[index] == -1) { int tmp = create_x(); right[index] = tmp; } assert(right[index] != -1); update_row(m, r, right[index], x, val); } data[index] = 0; if (left[index] != -1) data[index] += data[left[index]]; if (right[index] != -1) data[index] += data[right[index]]; } void update_grid(int d, int u, int index, int x, int y, int val) { if (y >= u || d > y) return; if (root[index] == -1) { int tmp = create_x(); root[index] = tmp; } assert(root[index] != -1); update_row(ll, rr, root[index], x, val); if (d + 1 == u) return; int m = d+u>>1; if (m > y) { if (down[index] == -1) { int tmp = create_y(); down[index] = tmp;; } assert(down[index] != -1); update_grid(d, m, down[index], x, y, val); } else { if (up[index] == -1) { int tmp = create_y(); up[index] = tmp; } assert(up[index] != -1); update_grid(m, u, up[index], x, y, val); } } int get_row(int l, int r, int index, int xs, int xe)const { if (xs >= r || l >= xe || index == -1) return 0; if (xe >= r && l >= xs) return data[index]; int m = l+r>>1; int lres = get_row(l, m, left[index], xs, xe); int rres = get_row(m, r, right[index], xs, xe); return lres + rres; } int get_grid(int d, int u, int index, int xs, int xe, int ys, int ye)const { if (ys >= u || d >= ye || index == -1) return 0; if (ye >= u && d >= ys) return get_row(ll, rr, root[index], xs, xe); int m = d+u>>1; int dres = get_grid(d, m, down[index], xs, xe, ys, ye); int ures = get_grid(m, u, up[index], xs, xe, ys, ye); return dres + ures; } void update(int x, int y, int val) { update_grid(dd, uu, 0, x, y, val); } int get(int xs, int xe, int ys, int ye)const { return get_grid(dd, uu, 0, xs, xe, ys, ye); } void clear() { for (int& i : data) i = 0; } }; const int BOTTOM_LEFT = 0; void solve2d() { int n, d, m; cin >> n >> d >> m; vector<array<int, 2>> v(n); //SegTree2d st[] = {SegTree2d(0, m, -2*m, 2*m), SegTree2d(0, m, -2*m, 2*m), SegTree2d(0, m, -2*m, 2*m), SegTree2d(0, m, -2*m, 2*m) } ; SegTree2d st(0, m, -2*m, 2*m); for (auto& [x, y] : v) { cin >> x >> y; x--, y--; } sort(v.begin(), v.end()); int64_t encounters = 0; for (auto [x, y] : v) { encounters += st.get(0, y+1, -2*m+1, d-x-y+1); st.update(y, -x-y, 1); } st.clear(); for (auto [x, y] : v) { encounters += st.get(y+1, m, -2*m+1, d-x+y+1); st.update(y, y-x, 1); } st.clear(); for (int i = v.size()-1; i >= 0; i--) { auto [x, y] = v[i]; encounters += st.get(0, y+1, -2*m+1, d+x-y+1); st.update(y, x-y, 1); } st.clear(); for (int i = v.size()-1; i >= 0; i--) { auto [x, y] = v[i]; encounters += st.get(y+1, m, -2*m+1, d+x+y+1); st.update(y, x+y, 1); } cout << (encounters / 2) << "\n"; } struct BIT3D { int a, b, c; vector<vector<vector<int>>> data; BIT3D(int a, int b, int c) : a(a), b(b), c(c), data(a+1, vector<vector<int>>(b+1, vector<int>(c+1))) {} void update(int x, int _y, int _z, int val) { for (++x;x<=a;x+=x&(-x)) for (int y=_y+1;y<=b;y+=y&(-y)) for (int z=_z+1;z<=c;z+=z&(-z)) data[x][y][z] += val; } int get(int x, int _y, int _z) { int res = 0; for (;x;x-=x&(-x)) for (int y=_y;y;y-=y&(-y)) for (int z=_z;z;z-=z&(-z)) res += data[x][y][z]; return res; } int query(int xl, int xr, int yl, int yr, int zl, int zr) { int a3 = get(xr, yr, zr); int a2 = get(xl, yr, zr); int b2 = get(xr, yl, zr); int c2 = get(xr, yr, zl); int a1 = get(xr, yl, zl); int b1 = get(xl, yr, zl); int c1 = get(xl, yl, zr); int a0 = get(xl, yl, zl); return a3 - a2 - b2 - c2 + a1 + b1 + c1 - a0; } void reset() { for (int x = 1; x <= a; x++) for (int y = 1; y <= b; y++) for (int z = 1; z <= c; z++) data[x][y][z] = 0; } }; int64_t add_result(int a, int b, int c, const vector<array<int, 3>>& v, BIT3D& bit, int m, int d) { bit.reset(); array<int, 3> pad = {a, b, c}; int64_t res = 0; int bonus = 0; for (int i : pad) if (i < 0) bonus += m; for (auto [x, y, z] : v) { int y_start = 0, y_end = y; if (b == 1) y_start = y, y_end = m; int z_start = 0, z_end = z; if (c == 1) z_start = z, z_end = m; int addition = a * x + y * b + c * z; res += bit.query(y_start, y_end, z_start, z_end, 0, min(d + addition + 1 + bonus, 3*m)); bit.update(y, z, addition + bonus, 1); } return res; } int64_t __find(int a, const vector<array<int, 3>>& v, BIT3D& bit, int m, int d) { int64_t res = 0; for (int b = -1; b <= 1; b+=2) for (int c = -1; c <= 1; c+=2) res += add_result(a, b, c, v, bit, m, d); return res; } void solve3d() { int n, d, m; cin >> n >> d >> m; BIT3D bit(m, m, 3*m); vector<array<int, 3>> v(n); for (auto& [x, y, z] : v) { cin >> x >> y >> z; x--, y--, z--; } sort(v.begin(), v.end()); int64_t res = __find(-1, v, bit, m, d); reverse(v.begin(), v.end()); res += __find(1, v, bit, m, d); cout << (res / 2) << "\n"; } int32_t main() { int b; cin >> b; if (b == 1) solve1d(); else if (b == 2) solve2d(); else solve3d(); }

Compilation message (stderr)

pairs.cpp: In member function 'void SegTree1d::update(int, int, int, int, int)':
pairs.cpp:38:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   38 |                 int m = l+r>>1;
      |                         ~^~
pairs.cpp: In member function 'int SegTree1d::get(int, int, int, int, int)':
pairs.cpp:49:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
   49 |                 int m = l+r>>1;
      |                         ~^~
pairs.cpp: In constructor 'SegTree2d::SegTree2d(int, int, int, int)':
pairs.cpp:86:27: warning: 'SegTree2d::up' will be initialized after [-Wreorder]
   86 |         vector<int> down, up;
      |                           ^~
pairs.cpp:86:21: warning:   'std::vector<int> SegTree2d::down' [-Wreorder]
   86 |         vector<int> down, up;
      |                     ^~~~
pairs.cpp:87:9: warning:   when initialized here [-Wreorder]
   87 |         SegTree2d (int ll, int rr, int dd, int uu) : ll(ll), rr(rr), uu(uu), dd(dd), root(1, -1), up(1, -1), down(1, -1) {}
      |         ^~~~~~~~~
pairs.cpp: In member function 'void SegTree2d::update_row(int, int, int, int, int)':
pairs.cpp:113:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  113 |                 int m = l+r>>1;
      |                         ~^~
pairs.cpp: In member function 'void SegTree2d::update_grid(int, int, int, int, int, int)':
pairs.cpp:153:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  153 |                 int m = d+u>>1;
      |                         ~^~
pairs.cpp: In member function 'int SegTree2d::get_row(int, int, int, int, int) const':
pairs.cpp:181:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  181 |                 int m = l+r>>1;
      |                         ~^~
pairs.cpp: In member function 'int SegTree2d::get_grid(int, int, int, int, int, int, int) const':
pairs.cpp:192:26: warning: suggest parentheses around '+' inside '>>' [-Wparentheses]
  192 |                 int m = d+u>>1;
      |                         ~^~
#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...
#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...