답안 #762883

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
762883 2023-06-21T23:19:35 Z caganyanmaz Pairs (IOI07_pairs) C++17
82 / 100
3479 ms 524288 KB
#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

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;
      |                         ~^~
# 결과 실행 시간 메모리 Grader output
1 Correct 0 ms 212 KB Output is correct
2 Correct 0 ms 212 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 724 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 39 ms 724 KB Output is correct
2 Correct 29 ms 724 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 195 ms 23280 KB Output is correct
2 Correct 107 ms 23276 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 197 ms 23276 KB Output is correct
2 Correct 86 ms 4916 KB Output is correct
3 Correct 70 ms 1368 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 31 ms 11964 KB Output is correct
2 Correct 28 ms 12060 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 343 ms 2612 KB Output is correct
2 Correct 301 ms 2648 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1220 ms 67016 KB Output is correct
2 Correct 1180 ms 67064 KB Output is correct
3 Correct 857 ms 34072 KB Output is correct
4 Correct 1096 ms 49752 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Runtime error 3479 ms 524288 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 9 ms 5668 KB Output is correct
2 Correct 13 ms 5588 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 84 ms 1984 KB Output is correct
2 Incorrect 84 ms 2104 KB Output isn't correct
3 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 216 ms 5040 KB Output is correct
2 Correct 208 ms 5068 KB Output is correct
3 Correct 206 ms 5028 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 264 ms 7588 KB Output is correct
2 Correct 252 ms 7592 KB Output is correct
3 Correct 233 ms 7584 KB Output is correct