Submission #1347068

#TimeUsernameProblemLanguageResultExecution timeMemory
1347068anangoJousting tournament (IOI12_tournament)C++20
100 / 100
297 ms7216 KiB
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace std;
using namespace __gnu_pbds;

typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> ordered_set;


//NOTE: NO DEFINE INT LONG LONG HERE
//once the knight wins a joust, it doesn't actually matter where exactly in that jousting range the knight started
//they could even be to the left or right of it
//if the late knight didn't exist, and the original query was from L to R in the original sequence
//then with the late knight, the new range is L to R-1 along with the late knight (if they're involved)
//and just L to R if they aren't involved
//thus to win a joust they must be higher ranked than each of L to R-1 IN THE REDUCED SEQUENCE
//we can expand back the indices from the end to the start
//to find what original-line indices they correspond to
//each corresponds to a range based on jousting reductions
//like map whole subintervals onto single points after a jousting reduction
//so now we reduce everything to the original sequence
//then take a difference array to process the summations offline, so
//add 1 to the interval L to R-1 essentially where L to R-1 is the remapped range
//when doing the initial mapping it's purely index-range to index so it's deterministic
//in fact even easier, just map initial indices to later on indices and so on til final indices
//like go[i] = the index i is mapped onto in the final transformation of ranges to points
//then it can be inverted and difference-arrayed
//actually this seems hard to implement
//let's just do a PBDS to keep track of the ranges...
//so keep track of j in the set, j being the start of the consecutive block that was mapped to the number i through the joustings

int GetBestPosition(int N, int C, int R, int *K, int *S, int *E) {
    vector<pair<int,int>> originalised_ranges;
    ordered_set o;
    for (int i=0; i<=N; i++) {
        o.insert(i);
    }
    for (int round=0; round<C; round++) {
        int l = *o.find_by_order(S[round]);
        int r = *o.find_by_order(E[round]+1); r--;
        originalised_ranges.push_back({l,r});
        //we want to store only the starts of blocks
        //so anything from S[round] to E[round]
        vector<int> removals;
        for (int i=S[round]+1; i<=E[round]; i++) {
            removals.push_back(*o.find_by_order(i));
        } //horribly inefficient but it's fine
        for (int i:removals) {
            o.erase(i);
        }
    }
    //first do it inefficiently O(n^2) should get 49/100
    vector<int> wins(N,0);
    for (auto i:originalised_ranges) {
        //only win if we're better than the entire range
        int fail = 0;
        for (int j=i.first; j<i.second; j++) {
            if (K[j] > R) {
                fail=1;
                break;
            }
        }
        //cout << i.first << " " << i.second << " " << fail << endl;
        if (fail) continue;
        for (int j=i.first; j<i.second; j++) {
            wins[j]++;
        }
    }
    for (int i=0; i<N; i++) {
        //cout << i << " " << wins[i] << endl;
    }
    int res = max_element(wins.begin(), wins.end())-wins.begin();
    return res;
}

#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...