답안 #801951

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
801951 2023-08-02T08:40:19 Z 반딧불(#10089) IOI 바이러스 (JOI21_fever) C++17
6 / 100
1 ms 724 KB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct Point{
    ll x, y;
    int idx;
    Point(){}
    Point(ll x, ll y): x(x), y(y){}
    Point(ll x, ll y, int idx): x(x), y(y), idx(idx){}

    bool operator<(const Point &r)const{
        if(x != r.x) return x < r.x;
        return y < r.y;
    }
};

int n;
Point arr[100002];
int ans;

void makeTrees();
void init();
void solve(int);

int main(){
    scanf("%d", &n);
    for(int i=0; i<n; i++){
        scanf("%lld %lld", &arr[i].x, &arr[i].y);
        arr[i].x*=2, arr[i].y*=2, arr[i].idx = i;
    }
    makeTrees();
    for(int d=0; d<4; d++){
        init();
        solve(d);
    }
    printf("%d", ans);
}

const ll INF = 3e18;
struct segTree{
    ll plusMin[400002], plusLazy[400002], plusVal[400002]; int plusIdx[400002];
    ll minusMin[400002], minusLazy[400002], minusVal[400002]; int minusIdx[400002];
    ll val[400002];

    void merge(int i){
        val[i] = min(val[i*2], val[i*2+1]);
        plusMin[i] = min(plusMin[i*2], plusMin[i*2+1]);
        plusVal[i] = min(plusVal[i*2], plusVal[i*2+1]);
        minusMin[i] = min(minusMin[i*2], minusMin[i*2+1]);
        minusVal[i] = min(minusVal[i*2], minusVal[i*2+1]);
        plusIdx[i] = (plusVal[i*2] <= plusVal[i*2+1]) ? plusIdx[i*2] : plusIdx[i*2+1];
        minusIdx[i] = (minusVal[i*2] <= minusVal[i*2+1]) ? minusIdx[i*2] : minusIdx[i*2+1];
    }

    void init(int i, int l, int r, ll *arr){
        plusMin[i] = minusMin[i] = plusLazy[i] = minusLazy[i] = INF;
        if(l==r){
            val[i] = arr[l];
            plusVal[i] = val[i] + plusMin[i];
            minusVal[i] = -val[i] + minusMin[i];
            plusIdx[i] = minusIdx[i] = l;
            return;
        }
        int m = (l+r)>>1;
        init(i*2, l, m, arr);
        init(i*2+1, m+1, r, arr);
        merge(i);
    }

    void propagate(int i, int l, int r){
        if(plusLazy[i] != INF){
            plusMin[i] = min(plusMin[i], plusLazy[i]);
            plusVal[i] = min(plusVal[i], val[i] + plusMin[i]);
            if(l!=r) plusLazy[i*2] = min(plusLazy[i*2], plusLazy[i]), plusLazy[i*2+1] = min(plusLazy[i*2+1], plusLazy[i]);
            plusLazy[i] = INF;
        }
        if(minusLazy[i] != INF){
            minusMin[i] = min(minusMin[i], minusLazy[i]);
            minusVal[i] = min(minusVal[i], -val[i] + minusMin[i]);
            if(l!=r) minusLazy[i*2] = min(minusLazy[i*2], minusLazy[i]), minusLazy[i*2+1] = min(minusLazy[i*2+1], minusLazy[i]);
            minusLazy[i] = INF;
        }
    }

    void updatePlus(int i, int l, int r, int s, int e, ll v){
        propagate(i, l, r);
        if(r<s || e<l) return;
        if(s<=l && r<=e){
            plusLazy[i] = v;
            propagate(i, l, r);
            return;
        }
        int m = (l+r)>>1;
        updatePlus(i*2, l, m, s, e, v);
        updatePlus(i*2+1, m+1, r, s, e, v);
        merge(i);
    }

    void updateMinus(int i, int l, int r, int s, int e, ll v){
        propagate(i, l, r);
        if(r<s || e<l) return;
        if(s<=l && r<=e){
            minusLazy[i] = v;
            propagate(i, l, r);
            return;
        }
        int m = (l+r)>>1;
        updateMinus(i*2, l, m, s, e, v);
        updateMinus(i*2+1, m+1, r, s, e, v);
        merge(i);
    }

    pair<ll, int> query(int i, int l, int r, int s, int e){
        propagate(i, l, r);
        if(r<s || e<l) return make_pair(INF, -1);
        if(s<=l && r<=e) return make_pair(min(plusVal[i], minusVal[i]), plusVal[i]<minusVal[i]?plusIdx[i]:minusIdx[i]);
        int m = (l+r)>>1;
        return min(query(i*2, l, m, s, e), query(i*2+1, m+1, r, s, e));
    }

    void updateOne(int i, int l, int r, int x){
        propagate(i, l, r);
        if(l==r){
            val[i] = plusVal[i] = minusVal[i] = INF;
            return;
        }
        int m = (l+r)>>1;
        if(x<=m) updateOne(i*2, l, m, x), propagate(i*2+1, m+1, r);
        else updateOne(i*2+1, m+1, r, x), propagate(i*2, l, m);
        merge(i);
    }
} tree[4];
vector<Point> order[4];
int idx[4][100002];
int L[4][100002], R[4][100002];

ll tarr[100002];

void makeTrees(){
    for(int i=0; i<n; i++){
        for(int j=0; j<4; j++) order[j].push_back(arr[i]);
    }

    sort(order[0].begin(), order[0].end(), [&](Point &a, Point &b){return a.y != b.y ? a.y < b.y : a.x < b.x;});
    sort(order[1].begin(), order[1].end(), [&](Point &a, Point &b){return a.x != b.x ? a.x < b.x : a.y < b.y;});
    sort(order[2].begin(), order[2].end(), [&](Point &a, Point &b){return a.y-a.x != b.y-b.x ? a.y-a.x<b.y-b.x : a.x<b.x;});
    sort(order[3].begin(), order[3].end(), [&](Point &a, Point &b){return a.y+a.x != b.y+b.x ? a.y+a.x<b.y+b.x : a.x<b.x;});

    for(int d=0; d<4; d++) for(int i=0; i<n; i++) idx[d][order[d][i].idx] = i;

    /// 0 �����: y
    for(int i=0; i<n; i++){
        int j = i;
        while(j+1 < n && order[0][i].y == order[0][j+1].y) j++;
        for(int s=i; s<=j; s++) L[0][s] = i, R[0][s] = j;
    }
    /// 1 �����: x
    for(int i=0; i<n; i++){
        int j = i;
        while(j+1 < n && order[1][i].x == order[1][j+1].x) j++;
        for(int s=i; s<=j; s++) L[1][s] = i, R[1][s] = j;
    }
    /// 2 �����: y-x
    for(int i=0; i<n; i++){
        int j = i;
        while(j+1 < n && order[2][i].y-order[2][i].x == order[2][j+1].y-order[2][j+1].x) j++;
        for(int s=i; s<=j; s++) L[2][s] = i, R[2][s] = j;
    }
    /// 3 �����: y+x
    for(int i=0; i<n; i++){
        int j = i;
        while(j+1 < n && order[3][i].y+order[3][i].x == order[3][j+1].y+order[3][j+1].x) j++;
        for(int s=i; s<=j; s++) L[3][s] = i, R[3][s] = j;
    }
}

void init(){
    /// Ʈ�� ����
    /// 0: ���� 1/2 arr[i].x
    for(int i=0; i<n; i++){
        tarr[i] = order[0][i].x / 2;
    }
    tree[0].init(1, 0, n-1, tarr);
    /// 1: ���� 1/2 arr[i].y
    for(int i=0; i<n; i++){
        tarr[i] = order[1][i].y / 2;
    }
    tree[1].init(1, 0, n-1, tarr);
    /// 2: ���� arr[i].x
    for(int i=0; i<n; i++){
        tarr[i] = order[2][i].x;
    }
    tree[2].init(1, 0, n-1, tarr);
    /// 3: ���� arr[i].x
    for(int i=0; i<n; i++){
        tarr[i] = order[3][i].x;
    }
    tree[3].init(1, 0, n-1, tarr);
}

bool visited[100002];

struct dat{
    int x, dir; ll d;
    dat(){}
    dat(int x, int dir, ll d): x(x), dir(dir), d(d){}
    bool operator<(const dat &r)const{
        return d>r.d;
    }
};

void pickup(int x, int d, ll t){
    /// ���� ��� Ʈ������ ��������
    for(int d=0; d<4; d++){
        tree[d].updateOne(1, 0, n-1, idx[d][x]);
    }

    /// �״����� Ʈ���� ������ ������
    if(d == 0){ /// ������ ����
        int l, r, i;

        /// 1�� ����: tree[2]���� �ڱ⺸�� ������
        i = idx[2][x];
        r = R[2][i], l = lower_bound(order[2].begin()+L[2][i], order[2].begin()+R[2][i]+1, Point(arr[x].x+t, INF)) - order[2].begin();
        if(l<=r) tree[2].updatePlus(1, 0, n-1, l, r, -arr[x].x);

        /// 3�� ����: tree[3]���� �ڱ⺸�� ������
        i = idx[3][x];
        r = R[3][i], l = lower_bound(order[3].begin()+L[3][i], order[3].begin()+R[3][i]+1, Point(arr[x].x+t, INF)) - order[3].begin();
        if(l<=r) tree[3].updatePlus(1, 0, n-1, l, r, -arr[x].x);

        /// 2�� ����: tree[0]���� �ڱ⺸�� ������
        i = idx[0][x];
        r = R[0][i], l = lower_bound(order[0].begin()+L[0][i], order[0].begin()+R[0][i]+1, Point(arr[x].x+t+t, INF)) - order[0].begin();
        if(l<=r) tree[0].updatePlus(1, 0, n-1, l, r, -arr[x].x/2);
    }

    else if(d == 3){ /// ���� ����
        int l, r, i;

        /// 0�� ����: tree[3]���� �ڱ⺸�� ����
        i = idx[3][x];
        l = L[3][i], r = upper_bound(order[3].begin()+L[3][i], order[3].begin()+R[3][i]+1, Point(arr[x].x-t, -INF)) - order[3].begin() - 1;
        if(l<=r) tree[3].updateMinus(1, 0, n-1, l, r, arr[x].x);

        /// 2�� ����: tree[2]���� �ڱ⺸�� ������
        i = idx[2][x];
        r = R[2][i], l = lower_bound(order[2].begin()+L[2][i], order[2].begin()+R[2][i]+1, Point(arr[x].x+t, INF)) - order[2].begin();
        if(l<=r) tree[2].updatePlus(1, 0, n-1, l, r, -arr[x].x);

        /// 1�� ����: tree[1]���� �ڱ⺸�� ������
        i = idx[0][x];
        r = R[0][i], l = lower_bound(order[0].begin()+L[0][i], order[0].begin()+R[0][i]+1, Point(arr[x].x, arr[x].y+t)) - order[0].begin();
        if(l<=r) tree[0].updatePlus(1, 0, n-1, l, r, -arr[x].y/2);
    }
}

void solve(int d){
    int cnt = 1;
    pickup(0, d, 0);
    while(1){
        pair<ll, int> mn[4];
        for(int d=0; d<4; d++){
            mn[d] = tree[d].query(1, 0, n-1, 0, n-1);
            mn[d].second = order[d][mn[d].second].idx;
        }
        int idx = min_element(mn, mn+4) - mn;
        if(mn[idx].first >= 1e18) break;
        pickup(mn[idx].second, idx, mn[idx].first);
        cnt++;
    }
    ans = max(ans, cnt);
}

Compilation message

fever.cpp: In function 'int main()':
fever.cpp:29:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   29 |     scanf("%d", &n);
      |     ~~~~~^~~~~~~~~~
fever.cpp:31:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   31 |         scanf("%lld %lld", &arr[i].x, &arr[i].y);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 596 KB Output is correct
2 Correct 1 ms 616 KB Output is correct
3 Correct 1 ms 596 KB Output is correct
4 Correct 1 ms 596 KB Output is correct
5 Incorrect 1 ms 596 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 596 KB Output is correct
2 Correct 1 ms 616 KB Output is correct
3 Correct 1 ms 596 KB Output is correct
4 Correct 1 ms 596 KB Output is correct
5 Incorrect 1 ms 596 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 724 KB Output is correct
2 Correct 1 ms 724 KB Output is correct
3 Correct 0 ms 724 KB Output is correct
4 Correct 1 ms 724 KB Output is correct
5 Correct 1 ms 724 KB Output is correct
6 Correct 1 ms 724 KB Output is correct
7 Correct 1 ms 724 KB Output is correct
8 Correct 1 ms 724 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 596 KB Output is correct
2 Correct 1 ms 616 KB Output is correct
3 Correct 1 ms 596 KB Output is correct
4 Correct 1 ms 596 KB Output is correct
5 Incorrect 1 ms 596 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 596 KB Output is correct
2 Correct 1 ms 616 KB Output is correct
3 Correct 1 ms 596 KB Output is correct
4 Correct 1 ms 596 KB Output is correct
5 Incorrect 1 ms 596 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 596 KB Output is correct
2 Correct 1 ms 616 KB Output is correct
3 Correct 1 ms 596 KB Output is correct
4 Correct 1 ms 596 KB Output is correct
5 Incorrect 1 ms 596 KB Output isn't correct
6 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 1 ms 596 KB Output is correct
2 Correct 1 ms 616 KB Output is correct
3 Correct 1 ms 596 KB Output is correct
4 Correct 1 ms 596 KB Output is correct
5 Incorrect 1 ms 596 KB Output isn't correct
6 Halted 0 ms 0 KB -