Submission #1323810

#TimeUsernameProblemLanguageResultExecution timeMemory
1323810TymondNaval battle (CEOI24_battle)C++20
100 / 100
644 ms88008 KiB
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using ld = long double;
#define fi first
#define se second
#define vi vector<int>
#define vll vector<long long>
#define pii pair<int, int>
#define pll pair<long long, long long>
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define all(x) (x).begin(), (x).end()
#define sz(x) (int)(x).size()
mt19937 rng(chrono::high_resolution_clock::now().time_since_epoch().count());
mt19937_64 rng64(chrono::high_resolution_clock::now().time_since_epoch().count());
inline int rand(int l,int r){return uniform_int_distribution<int>(l, r)(rng);}
inline ll rand(ll l,ll r){return uniform_int_distribution<ll>(l, r)(rng64);}
#ifdef DEBUG
auto&operator<<(auto&o,pair<auto,auto>p){return o<<"("<<p.first<<", "<<p.second<<")";}
auto operator<<(auto&o,auto x)->decltype(x.end(),o){o<<"{";int i=0;for(auto e:x)o<<","+!i++<<e;return o<<"}";}
#define debug(X...)cerr<<"["#X"]: ",[](auto...$){((cerr<<$<<"; "),...)<<endl;}(X)
#else
#define debug(...){}
#endif

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

struct pair_hash{
  size_t operator()(const pair<int,int>&x)const{
    return hash<long long>()(((long long)x.first)^(((long long)x.second)<<32));
  }
};

const int MAXN = 2e5 + 7;
int X[MAXN];
int Y[MAXN];
char type[MAXN];
int deleted[MAXN];
map<int, set<pii>> row;
map<int, set<pii>> column;
//pierwsza przekątna -> x + y
map<int, set<pii>> firstDiagonalUp;
map<int, set<pii>> firstDiagonalDown;
//druga przekątna -> x - y
map<int, set<pii>> secondDiagonalUp;
map<int, set<pii>> secondDiagonalDown;
int n;
priority_queue<pair<int, pii>> pq;

void init(){
    for(auto&[xddd, curr] : row){
        auto it = curr.begin();
        while(it != curr.end()){
            if(type[(*it).se] == 'W'){
                it++;
                continue;
            }

            auto it2 = it;
            it2++;
            if(it2 == curr.end()){
                break;
            }

            if(type[(*it2).se] == 'E'){
                it = it2;
                continue;
            }
            pq.push(mp(-abs((*it).fi - (*it2).fi) / 2, mp((*it).se, (*it2).se)));
            it = it2;
            it2++;
        }
    }

    for(auto&[xddd, curr] : column){
        auto it = curr.begin();
        while(it != curr.end()){
            if(type[(*it).se] == 'N'){
                it++;
                continue;
            }

            auto it2 = it;
            it2++;
            if(it2 == curr.end()){
                break;
            }

            if(type[(*it2).se] == 'S'){
                it = it2;
                continue;
            }
            pq.push(mp(-abs((*it).fi - (*it2).fi) / 2, mp((*it).se, (*it2).se)));
            it = it2;
            it2++;
        }
    }

    for(auto&[xddd, curr] : firstDiagonalUp){
        auto it = curr.begin();
        while(it != curr.end()){
            if(type[(*it).se] == 'W'){
                it++;
                continue;
            }

            auto it2 = it;
            it2++;
            if(it2 == curr.end()){
                break;
            }

            if(type[(*it2).se] == 'N'){
                it = it2;
                continue;
            }
            //cerr << (*it).se << ' ' << (*it2).se << '\n';
            pq.push(mp(-abs((*it).fi - (*it2).fi), mp((*it).se, (*it2).se)));
            it = it2;
            it2++;
        }
    }

    for(auto&[xddd, curr] : firstDiagonalDown){
        auto it = curr.begin();
        while(it != curr.end()){
            if(type[(*it).se] == 'S'){
                it++;
                continue;
            }

            auto it2 = it;
            it2++;
            if(it2 == curr.end()){
                break;
            }

            if(type[(*it2).se] == 'E'){
                it = it2;
                continue;
            }
            pq.push(mp(-abs((*it).fi - (*it2).fi), mp((*it).se, (*it2).se)));
            it = it2;
            it2++;
        }
    }

    for(auto&[xddd, curr] : secondDiagonalUp){
        auto it = curr.begin();
        while(it != curr.end()){
            if(type[(*it).se] == 'N'){
                it++;
                continue;
            }

            auto it2 = it;
            it2++;
            if(it2 == curr.end()){
                break;
            }

            if(type[(*it2).se] == 'E'){
                it = it2;
                continue;
            }
            pq.push(mp(-abs((*it).fi - (*it2).fi), mp((*it).se, (*it2).se)));
            it = it2;
            it2++;
        }
    }

    for(auto&[xddd, curr] : secondDiagonalDown){
        auto it = curr.begin();
        while(it != curr.end()){
            if(type[(*it).se] == 'W'){
                it++;
                continue;
            }

            auto it2 = it;
            it2++;
            if(it2 == curr.end()){
                break;
            }

            if(type[(*it2).se] == 'S'){
                it = it2;
                continue;
            }
            pq.push(mp(-abs((*it).fi - (*it2).fi), mp((*it).se, (*it2).se)));
            it = it2;
            it2++;
        }
    }
}

//pierwsze jest a, drugie jest b
void del(int a, int b, int w, set<pii>& curr, int flag = 0){
   //  cerr << a << ' ' << b << ' ' << w << ' ' << flag << '\n';
   //  cerr << sz(curr) << '\n';
   // for(auto ele : curr){
   //     cerr << ele << ' ' << type[ele.se] << '\n';
   // }
   // cerr << '\n';
    auto it = curr.find(mp((flag ? Y[a] : X[a]), a));
    auto it2 = curr.find(mp((flag ? Y[b] : X[b]), b));
    if(deleted[b] != 0){
        ++it2;
    }
    if(((deleted[a] != 0 && it != curr.begin()) || deleted[a] == 0) && it2 != curr.end()){
        if(deleted[a] != 0){
            --it;
        }
        
        //cerr << (*it) << ' ' << (*it2) << '\n';
        if(type[(*it).se] == type[a] && type[(*it2).se] == type[b]){
            pq.push(mp(-abs((*it).fi - (*it2).fi) / w, mp((*it).se, (*it2).se)));
        }
    }

    if(deleted[a] != 0){
        curr.erase(mp((flag ? Y[a] : X[a]), a));
    }

    if(deleted[b] != 0){
        curr.erase(mp((flag ? Y[b] : X[b]), b));
    }
}

void deleteInfo(int a, int b){
   // cerr << "DELETING: " << a << ' ' << b << '\n';
   // cerr << type[a] << ' ' << type[b] << '\n';
    if(type[a] == 'N'){
        if(type[b] == 'W'){
            //cerr << "INTERESTING\n";
            del(a, b, 1, firstDiagonalUp[X[a] + Y[a]]);
            return;
        }else if(type[b] == 'E'){
            del(b, a, 1, secondDiagonalUp[X[a] - Y[a]]);
            return;
        }else if(type[b] == 'S'){
            del(b, a, 2, column[X[a]], 1);
            return;
        }
    }else if(type[a] == 'W'){
        if(type[b] == 'E'){
            del(b, a, 2, row[Y[a]]);
            return;
        }else if(type[b] == 'S'){
            del(b, a, 1, secondDiagonalDown[X[a] - Y[a]]);
            return;
        }
    }else if(type[a] == 'E' && type[b] == 'S'){
         del(a, b, 1, firstDiagonalDown[X[a] + Y[a]]);
         return;
    }
    swap(a, b);
    deleteInfo(a, b);
}

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

    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> X[i] >> Y[i] >> type[i];
        if(type[i] == 'S' || type[i] == 'N'){
            column[X[i]].insert(mp(Y[i], i));
        }else{
            row[Y[i]].insert(mp(X[i], i));
        }

        if(type[i] == 'N'){
            firstDiagonalUp[X[i] + Y[i]].insert(mp(X[i], i));
            secondDiagonalUp[X[i] - Y[i]].insert(mp(X[i], i));
        }else if(type[i] == 'S'){
            firstDiagonalDown[X[i] + Y[i]].insert(mp(X[i], i));
            secondDiagonalDown[X[i] - Y[i]].insert(mp(X[i], i));
        }else if(type[i] == 'W'){
            firstDiagonalUp[X[i] + Y[i]].insert(mp(X[i], i));
            secondDiagonalDown[X[i] - Y[i]].insert(mp(X[i], i));
        }else{
            firstDiagonalDown[X[i] + Y[i]].insert(mp(X[i], i));
            secondDiagonalUp[X[i] - Y[i]].insert(mp(X[i], i));
        }
    }

    init();
    while(sz(pq)){
        pair<int, pii> curr = pq.top();
        pq.pop();
        int a = curr.se.fi;
        int b = curr.se.se;
        if(a == b){
            continue;
        }
        //cerr << curr.fi << ' ' << a << ' ' << b << '\n';
        if(deleted[a] == 0 || deleted[b] == 0){
            if(deleted[a]){
                if(curr.fi == deleted[a]){
                    deleted[b] = curr.fi;
                }
            }else if(deleted[b]){
                if(curr.fi == deleted[b]){
                    deleted[a] = curr.fi;
                }
            }else{
                deleted[a] = curr.fi;
                deleted[b] = curr.fi;
            }
        }
        
        //cerr << deleted[a] << ' ' << deleted[b] << '\n';
        deleteInfo(a, b);
        //cerr << "======\n";
    }

  //  cerr << "ANS:\n";
    for(int i = 1; i <= n; i++){
        if(deleted[i] == 0){
            cout << i << '\n';
        }
    }

    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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...