Submission #480789

#TimeUsernameProblemLanguageResultExecution timeMemory
480789wiwihoTriangles (CEOI18_tri)C++14
75 / 100
3068 ms2496 KiB
#include "trilib.h"
#include<bits/stdc++.h>

#define eb emplace_back
#define iter(a) a.begin(), a.end()
#define lsort(a) sort(iter(a))
#define uni(a) a.resize(unique(iter(a)) - a.begin())
#define printv(a, b) {\
    for(auto pv : a) b << pv << " ";\
    b << "\n";\
}
#define mt make_tuple
#define mp make_pair
#define F first
#define S second

using namespace std;

typedef long long ll;

using tiii = tuple<int, int, int>;
using pii = pair<int, int>;

void waassert(bool b){
    if(b) return;
    cout << "OAO\n";
    exit(0);
}

int n;
vector<int> hull;
map<tiii, int> qry;

int query(int a, int b, int c){
    if(qry.find(mt(a, b, c)) != qry.end()) return qry[mt(a,b,c)];
    //waassert(a != b && b != c && c != a);
    return is_clockwise(a, b, c);
}

bool check0(int id, int i){
    int m = hull.size();
    int lst = (i - 1 + m) % m;
    int nxt = (i + 1) % m;
    return query(id, hull[lst], hull[i]) || query(id, hull[i], hull[nxt]);
}

bool check(int id, int i){
    int m = hull.size();
    int lst = (i - 1 + m) % m;
    int nxt = (i + 1) % m;
    return query(id, hull[lst], hull[i]) && query(id, hull[i], hull[nxt]);
}

void add(int id){
    //cerr << "test " << id << "\n";
    int m = hull.size();
    int l = 0, r = m - 1;
    while(l < r){
        int mid = (l + r + 1) / 2;
        if(query(id, hull[0], hull[mid]) == query(id, hull[0], hull[1])) l = mid;
        else r = mid - 1;
    }
    deque<int> a, b;
    for(int i = 0; i <= l; i++) a.eb(i);
    for(int i = l + 1; i < m; i++) b.eb(i);
    vector<vector<int>> del(4);
    while(!a.empty() && check0(id, a.front())){
        if(!check(id, a.front())) del[0].eb(a.front());
        a.pop_front();
    }
    while(!a.empty() && check0(id, a.back())){
        if(!check(id, a.back())) del[1].eb(a.back());
        a.pop_back();
    }
    while(!b.empty() && check0(id, b.front())){
        if(!check(id, b.front())) del[2].eb(b.front());
        b.pop_front();
    }
    while(!b.empty() && check0(id, b.back())){
        if(!check(id, b.back())) del[3].eb(b.back());
        b.pop_back();
    }

    /*cerr << "A ";
    printv(a, cerr);
    cerr << "B ";
    printv(b, cerr);
    for(int i = 0; i < 4; i++){
        cerr << "D" << i << " ";
        printv(del[i], cerr);
    }*/

    vector<int> tmp;
    tmp.swap(hull);

    bool ok1 = false, ok2 = false;
    auto put = [&](int i){
        if(ok1 && ok2) hull.eb(id);
        hull.eb(tmp[i]);
        if(ok1 && !ok2) hull.eb(id);
        ok1 = true;
        ok2 = true;
    };

    for(int i : del[0]) put(i);
    for(int i : a) hull.eb(tmp[i]), ok2 = false;
    for(int i : del[1]) put(i);
    for(int i : del[2]) put(i);
    for(int i : b) hull.eb(tmp[i]), ok2 = false;
    for(int i : del[3]) put(i);

    if(hull.size() == 3 && query(hull[0], hull[1], hull[2])){
        reverse(iter(hull));
    }
    
    //printv(hull, cerr);
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    n = get_n();
    if(query(1, 2, 3)){
        hull = {3, 2, 1};
    }
    else{
        hull = {1, 2, 3};
    }
    for(int i = 4; i <= n; i++) add(i);
    give_answer(hull.size());

    return 0;
}
#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...