QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#829301#9776. Best Friend, Worst Enemyucup-team5243WA 325ms23468kbC++1710.0kb2024-12-24 09:02:282024-12-24 09:02:42

Judging History

你现在查看的是最新测评结果

  • [2024-12-24 09:02:42]
  • 评测
  • 测评结果:WA
  • 用时:325ms
  • 内存:23468kb
  • [2024-12-24 09:02:28]
  • 提交

answer

#ifdef NACHIA
#define _GLIBCXX_DEBUG
#else
#define NDEBUG
#endif
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using i64 = long long;
using u64 = unsigned long long;
#define rep(i,n) for(int i=0; i<int(n); i++)
const i64 INF = 1001001001001001001;
template<typename A> void chmin(A& l, const A& r){ if(r < l) l = r; }
template<typename A> void chmax(A& l, const A& r){ if(l < r) l = r; }
using namespace std;

#include <tuple>

namespace nachia{

template<
    class S,
    S op(S l, S r)
>
struct Segtree {
private:
    int N;
    std::vector<S> A;
    int xN;

    void mergev(int i){
        if(i < N) A[i] = op(A[i*2], A[i*2+1]);
    }

    template<class E>
    int minLeft2(int r, E cmp, int a = 0, int b = 0, int i = -1) const {
        static S x;
        if(i == -1){ a=0; b=N; i=1; x=A[0]; }
        if(r <= a) return a;
        if(b <= r){
            S nx = op(A[i], x);
            if(cmp(nx)){ x = nx; return a; }
        }
        if(b - a == 1) return b;
        int q = minLeft2(r, cmp, (a+b)/2, b, i*2+1);
        if(q > (a+b)/2) return q;
        return minLeft2(r, cmp, a, (a+b)/2, i*2);
    }
    
    template<class E>
    int maxRight2(int l, E cmp, int a = 0, int b = 0, int i = -1) const {
        static S x;
        if(i == -1){ a=0; b=N; i=1; x=A[0]; }
        if(b <= l) return b;
        if(l <= a){
            S nx = op(x, A[i]);
            if(cmp(nx)){ x = nx; return b; }
        }
        if(b - a == 1) return a;
        int q = maxRight2(l, cmp, a, (a+b)/2, i*2);
        if(q < (a+b)/2) return q;
        return maxRight2(l, cmp, (a+b)/2, b, i*2+1);
    }

public:
    Segtree() : N(0) {}
    Segtree(int n, S e) : xN(n) {
        N = 1; while (N < n) N *= 2;
        A.assign(N * 2, e);
    }
    Segtree(const std::vector<S>& a, S e) : Segtree(a.size(), e){
        for(int i=0; i<(int)a.size(); i++) A[i + N] = a[i];
        for(int i=N-1; i>=1; i--) mergev(i);
    }

    S getE() const { return A[0]; }

    void set(int p, S x){
        p += N; A[p] = x;
        for(int d=1; (1<<d)<=N; d++) mergev(p>>d);
    }

    S get(int p) const { return A[N+p]; }

    S prod(int l, int r) const {
        l += N; r += N;
        S ql = A[0], qr = A[0];
        while(l<r){
            if(l&1) ql = op(ql, A[l++]);
            if(r&1) qr = op(A[--r], qr);
            l /= 2;
            r /= 2;
        }
        return op(ql, qr);
    }

    S allProd() const { return A[1]; }

    // bool cmp(S)
    template<class E>
    int minLeft(int r, E cmp) const {
        return minLeft2(r, cmp);
    }

    // bool cmp(S)
    template<class E>
    int maxRight(int l, E cmp) const {
        int x = maxRight2(l, cmp);
        return x > xN ? xN : x;
    }
};

} // namespace nachia


namespace nachia {

template<class T>
struct PointAddRangeSum{
private:
    static T addop(T l, T r){ return l + r; }
    using Base = Segtree<T, addop>;
    Base base;
public:
    PointAddRangeSum() {}
    PointAddRangeSum(int len, T Zero)
        : base(len, Zero){}
    PointAddRangeSum(const std::vector<T>& init, T Zero)
        : base(init, Zero){}
    T sum(int l, int r){ return base.prod(l, r); }
    T sum(){ return base.allProd(); }
    void set(int pos, T val){ base.set(pos, val); }
    void add(int pos, T val){ base.set(pos, base.get(pos) + val); }
    T get(int pos){ return base.get(pos); }
    int lBoundLeft(int from, T val){ return base.minLeft(from, [this,val](const T& x){ return x < val; }); }
    int uBoundLeft(int from, T val){ return base.minLeft(from, [this,val](const T& x){ return !(val < x); }); }
    int lBoundRight(int from, T val){ return base.maxRight(from, [this,val](const T& x){ return x < val; }); }
    int uBoundRight(int from, T val){ return base.maxRight(from, [this,val](const T& x){ return !(val < x); }); }
    template<class E>
    int minLeft(int r, E cmp){ return base.minLeft(r, cmp); }
    template<class E>
    int maxRight(int l, E cmp){ return base.maxRight(l, cmp); }
};

} // namespace nachia

string ToString(const vector<int>& l){
    string res = "[ ";
    for(auto i : l){
        res += to_string(i);
        res += " ";
    }
    res += "]";
    return res;
}

void testcase(){
    i64 N; cin >> N;
    vector<pair<int,int>> XY(N);
    rep(i,N){ int x,y; cin >> x >> y; XY[i] = { x,y }; }
    vector<int> IX(N);
    rep(i,N) IX[i] = i;
    sort(IX.begin(), IX.end(), 
        [&](int l, int r){ return XY[l] < XY[r]; });
    vector<int> IY(N);
    rep(i,N) IY[i] = i;
    sort(IY.begin(), IY.end(), 
        [&](int l, int r){
            auto [xl,yl] = XY[l];
            auto [xr,yr] = XY[r];
            return make_pair(yl,xl) < make_pair(yr,xr);
        });
    vector<int> OX(N), OY(N);
    rep(i,N) OX[IX[i]] = i;
    rep(i,N) OY[IY[i]] = i;
    //cout << "IX : " << ToString(IX) << "\n";
    //cout << "OX : " << ToString(OX) << "\n";
    //cout << "IY : " << ToString(IY) << "\n";
    //cout << "OY : " << ToString(OY) << "\n";
    //cout << endl;
    nachia::PointAddRangeSum<int> TX(N,0), TY(N,0);
    int dxs[4] = { -1, -1,  1,  1 };
    int dys[4] = { -1,  1,  1, -1 };
    int maxpol[4]; rep(d,4) maxpol[d] = -1000000000;
    auto maxManhattan = [&](int p) -> int {
        auto [x,y] = XY[p];
        int res = 0;
        rep(d,4) chmax(res, maxpol[d] - x * dxs[d] - y * dys[d]);
        return res;
    };
    vector<pair<int,int>> XYS(N);
    rep(i,N) XYS[i] = XY[IX[i]];
    auto exist = [&](int x, int y) -> int {
        int i = lower_bound(XYS.begin(), XYS.end(), make_pair(x,y)) - XYS.begin();
        //cout << "i = " << i << "  " << x << "," << y << endl;
        if(i < N && XYS[i] == make_pair(x,y)) return IX[i];
        return -1;
    };
    auto lbix = [&](vector<int>& a, int x) -> int {
        //cout << "a = " << ToString(a) << endl;
        //cout << "x = " << x << endl;
        return lower_bound(a.begin(), a.end(), x,
            [&](int l, int x){ return XY[l].first < x; }) - a.begin();
    };
    auto lbiy = [&](vector<int>& a, int x) -> int {
        //cout << "a = " << ToString(a) << endl;
        //cout << "x = " << x << endl;
        return lower_bound(a.begin(), a.end(), x,
            [&](int l, int x){ return XY[l].second < x; }) - a.begin();
    };

    auto dist1 = [&](int p, int q){
        auto [xp,yp] = XY[p];
        auto [xq,yq] = XY[q];
        return abs(xp-xq) + abs(yp-yq);
    };
    auto dist2 = [&](int p, int q){
        auto [xp,yp] = XY[p];
        auto [xq,yq] = XY[q];
        return max(abs(xp-xq), abs(yp-yq));
    };

    int K = 0;
    auto border = [&](int p) -> pair<int,int> {
        auto [x,y] = XY[p];
        int maxm = maxManhattan(p);
        int cntout = 0;
        int xli = lbix(IX, x - (maxm)/2);
        int xri = lbix(IX, x + (maxm)/2 + 1);
        int yli = lbiy(IY, y - (maxm)/2);
        int yri = lbiy(IY, y + (maxm)/2 + 1);
        cntout += K - TX.sum(xli, xri);
        cntout += K - TY.sum(yli, yri);
        //cout << "cntout = " << cntout << endl;
        int mincd = maxm;
        if(maxm % 2 == 0) rep(d,4){
            int ex = exist(x + maxm/2 * dxs[d], y + maxm/2 * dys[d]) >= 0 ? 1 : 0;
            if(ex){ cntout++; chmin(mincd, maxm/2); }
        }
        if(cntout < K) return {-1,-1};
        //cout << "mincd = " << mincd << endl;

        int xlbound = TX.uBoundLeft(xli, 0);
        if(xlbound != 0) chmin(mincd, x - XY[IX[xlbound-1]].first);
        int xrbound = TX.uBoundRight(xri, 0);
        if(xrbound != N) chmin(mincd, XY[IX[xrbound]].first - x);
        int ylbound = TY.uBoundLeft(yli, 0);
        if(ylbound != 0) chmin(mincd, y - XY[IY[ylbound-1]].second);
        int yrbound = TY.uBoundRight(yri, 0);
        if(yrbound != N) chmin(mincd, XY[IY[yrbound]].second - y);

        //cout << "mincd = " << mincd << endl;
        return { maxm, mincd };
    };
    
    struct Valid{
        int p;
        int maxdist1;
        int mindist2;
        vector<int> li;
    };
    vector<Valid> valids;
    
    for(int i=0; i<N; i++){
        auto [x,y] = XY[i];

        if(i >= 2){
            rep(vi,valids.size()){
                auto& v = valids[vi];
                int d1 = dist1(v.p, i);
                int d2 = dist2(v.p, i);
                if(v.maxdist1 < d1){ v.maxdist1 = d1; v.li.clear(); }
                if(v.mindist2 > d2){ v.mindist2 = d2; v.li.clear(); }
                if(v.maxdist1 > 2 * v.mindist2){
                    swap(valids.back(), v); valids.pop_back(); vi--; 
                    continue;
                }
                if(v.maxdist1 == d1 && v.mindist2 == d2) v.li.push_back(i);
            }
            auto [u,v] = border(i);
            if(u != -1){
                Valid q;
                q.p = i; q.maxdist1 = u; q.mindist2 = v;
                rep(d,4){
                    int p1 = exist(x + v*dxs[d], y + (u-v)*dys[d]);
                    if(p1 >= 0 && p1 < i) q.li.push_back(p1);
                    int p2 = exist(x + (u-v)*dxs[d], y + v*dys[d]);
                    if(p2 >= 0 && p2 < i) q.li.push_back(p2);
                }
                sort(q.li.begin(), q.li.end());
                q.li.erase(unique(q.li.begin(), q.li.end()), q.li.end());
                valids.push_back(move(q));
            }
            //cout << "valids : \n";
            //for(auto& v : valids) cout << "    (" << v.p << " " << v.maxdist1 << " " << v.mindist2 << " " << ToString(v.li) << ")\n";
            //cout << endl;
            int ans = 0;
            for(auto& v : valids) ans += int(v.li.size());
            cout << ans << "\n";
        } else if(i == 1){
            valids.push_back({ 0, dist1(0,1), dist2(0,1), {1} });
            valids.push_back({ 1, dist1(0,1), dist2(0,1), {0} });
            cout << "2\n";
        } else{ cout << "0\n"; }

        TX.add(OX[i], 1);
        TY.add(OY[i], 1);
        rep(d,4) chmax(maxpol[d], x * dxs[d] + y * dys[d]);
        K++;
    }
}

int main(){
    ios::sync_with_stdio(false); cin.tie(nullptr);
    testcase();
    return 0;
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 0ms
memory: 3496kb

input:

2
1 5
1 10

output:

0
2

result:

ok 2 number(s): "0 2"

Test #2:

score: 0
Accepted
time: 0ms
memory: 3800kb

input:

4
2 5
5 3
5 7
8 5

output:

0
2
4
4

result:

ok 4 number(s): "0 2 4 4"

Test #3:

score: 0
Accepted
time: 0ms
memory: 3496kb

input:

9
3 4
3 6
4 3
4 7
5 5
6 3
6 7
7 4
7 6

output:

0
2
1
0
4
5
6
7
8

result:

ok 9 numbers

Test #4:

score: 0
Accepted
time: 0ms
memory: 3612kb

input:

13
3 5
4 4
4 5
4 6
5 3
5 4
5 5
5 6
5 7
6 4
6 5
6 6
7 5

output:

0
2
4
7
2
2
5
2
2
3
3
4
4

result:

ok 13 numbers

Test #5:

score: -100
Wrong Answer
time: 325ms
memory: 23468kb

input:

384010
200000 1000000
200000 1000001
199999 1000000
200001 1000000
200000 999999
200000 1000002
200002 1000000
200000 999998
199998 1000000
199997 1000000
200003 1000000
200000 999997
200000 1000003
199996 1000000
200004 1000000
200000 1000004
200000 999996
199995 1000000
200000 1000005
200000 99999...

output:

0
2
4
7
10
2
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0...

result:

wrong answer 5th numbers differ - expected: '12', found: '10'