Submission #1043197

#TimeUsernameProblemLanguageResultExecution timeMemory
1043197mohitdmakRabbit Carrot (LMIO19_triusis)C++17
100 / 100
56 ms12372 KiB
/////////////////////////////////////////////// EPILOGUE ///////////////////////////////////////////////
// Author: @mohitdmak 
// NOTE: code inside this fxn at end of template or after importing it
// void start(){ }
/////////////////////////////////////////////// END ///////////////////////////////////////////////

/////////////////////////////////////////////// GCC AND LIBS OPTIMIZATIONS ///////////////////////////////////////////////
#pragma GCC optimize("Ofast")
// #pragma GCC optimize("O0") // for something related to double precision optimization? (checkout)
// // #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,fma") // below removed "avx2" as SPOJ gives runtime error due to "SIGILL" for some reason
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,fma")
#pragma GCC optimize("unroll-loops")
#include "bits/stdc++.h" // going for precompiling headers for stl lib collection (#include <bits/stdc++.h>) through make job
using namespace std;
#ifndef ONLINE_JUDGE
    #include <sys/resource.h>
#endif
/////////////////////////////////////////////// END ///////////////////////////////////////////////

/////////////////////////////////////////////// DEBUGGING FUNCTIONS ///////////////////////////////////////////////
// COUTing pairs 
template <typename S, typename V>
ostream& operator<<(ostream& os, const pair<S, V>& ppair) {
    os << "P:{" << ppair.first << "," << ppair.second << "}";
    return os;
}
// COUTing sets (only 1Ds at the moment)
// template <typename S, class Iterator>
template <typename S, typename V>
ostream& operator<<(ostream& os, const set<S, V>& sset) {
    os << "Set:[";
    for (auto element : sset) { os << element << ","; }
    os << "]";
    return os;
}
// COUTing multisets (only 1Ds at the moment)
// template <typename T, typename S, typename V>
template <typename S, typename V>
ostream& operator<<(ostream& os, const multiset<S, V>& mset) {
    os << "MSet:[";
    for (auto element : mset) { os << element << ","; }
    os << "]";
    return os;
}
// COUTing vectors (only 1Ds at the moment) 
template <typename S>
ostream& operator<<(ostream& os, const vector<S>& vvector) {
    os << "V:[";
    for (auto element : vvector) { os << element << ","; }
    os << "]";
    return os;
}
// COUTing deques 
template <typename S>
ostream& operator<<(ostream& os, const deque<S>& ddeque) {
    os << "Dq:[";
    for (auto element : ddeque) { os << element << ","; }
    os << "]";
    return os;
}
// COUTing maps (only 1Ds at the moment)
template <typename S, typename V>
ostream& operator<<(ostream& os, const map<S, V>& mmap) {
    os << "M:[";
    for (auto element : mmap) { os << element.first << ":" << element.second << ","; }
    os << "]";
    return os;
}
// COUTing unordered maps (only 1Ds at the moment)
template <typename S, typename V>
ostream& operator<<(ostream& os, const unordered_map<S, V>& mmap) {
    os << "uM:[";
    for (auto element : mmap) { os << element.first << ":" << element.second << ","; }
    os << "]";
    return os;
}
// COUTing queues
template <typename T>
ostream& operator<<(ostream& os, queue<T> mq) {
    os << "Q:[";
    while (mq.size()){
        T element = mq.front(); mq.pop();
        os << element << ",";
    }
    os << "]";
    return os;
}
// COUTing stacks
template <typename T>
ostream& operator<<(ostream& os, stack<T> mq) {
    os << "S:[";
    while (mq.size()){
        T element = mq.top(); mq.pop();
        os << element << ",";
    }
    os << "]";
    return os;
}
// COUTing priority_queue
// template <typename T, typename S, typename V>
template <typename T, typename S, typename V>
ostream& operator<<(ostream& os, const priority_queue<T, S, V>& mpq) {
    priority_queue<T, S, V> copyPQ(mpq);
    os << "PQ:[";
    while (copyPQ.size()) { os << copyPQ.top() << ","; copyPQ.pop(); }
    os << "]";
    return os;
}
/* debugging error variables and values */
#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); cerr << "\nDEBUG: "; err(_it, args); }
void err(istream_iterator<string> it) {}
template<typename T, typename... Args>
void err(istream_iterator<string> it, T a, Args... args) {
	cerr << *it << " = " << a << "; ";
	err(++it, args...);
}
vector<string> X_splitStr(string s, vector<string> delims){
    string curr = s;
    int curr_pos = 0;
    vector<string> tokenized;
    while(curr.size()){
        int delim_size = 0;
        for (string delim: delims){
            int curr_size = (int)curr.size();
            curr = curr.substr(0, curr.find(delim));
            if ((int)curr.size() != curr_size) delim_size = delim.size();
        }
        curr_pos += (int)curr.size() + delim_size;
        if (curr.size()) tokenized.push_back(curr);
        curr = s.substr(curr_pos);
    }
    return tokenized;
}
/////////////////////////////////////////////// END ///////////////////////////////////////////////

/////////////////////////////////////////////// SHORTHANDS / DEFINITIONS ///////////////////////////////////////////////
#define _n_ << "\n"  // newline
#define __ << " " << // space
const int BS = 21; // no of bits to print in X_BS
const int MOD = 1e9 + 7;
typedef long long ll;
vector<ll> FACTORIALS;
/////////////////////////////////////////////// END ///////////////////////////////////////////////

/////////////////////////////////////////////// UTILITY FUNCTIONS ///////////////////////////////////////////////
// Matrix ops like power (bin exponentiation), etc <==> (Template is just to support int / long long)
template<class T> struct X_Mat{
    vector<vector<T>> mat; int r, c, mod; // mod is used during mul ops
    X_Mat(): r(0), c(0) {} // default constructor (don't initialize vector 'o vector)
    X_Mat(int r_, int c_, int mod_ = 0, int val_ = 0): r(r_), c(c_), mod(mod_) { mat = vector<vector<T>>(r_, vector<T>(c, val_)); }
    X_Mat operator*(const X_Mat &mat2){ // mul op -> O(N^3) where |mat| ~ N x N
        assert(c == mat2.r); // m1 x m2 -> can only cross if of form [axb]X[bxc]
        X_Mat res(r, mat2.c, mod); // response matrix (carry forth mod info, initialize with 0s)
        for (int i = 0; i < r; i++) for (int j = 0; j < mat2.c; j++) for (int k = 0; k < c; k++){ // matrix mul
            if (!mod) res.mat[i][j] += mat[i][k] * mat2.mat[k][j];
            else res.mat[i][j] = (res.mat[i][j] + (1ll * mat[i][k] * mat2.mat[k][j] % mod)) % mod;
        }
        return res;
    }
    X_Mat operator*=(const X_Mat &mat2){ return *this = (*this) * mat2; } // simply assign res of mul op
    // O(N^3.log(p)) -> friend function to use externally, using bin exponentiation on matrices
    friend X_Mat X_MatPower(X_Mat m, ll p){ 
        assert(m.r == m.c); // only square matrices can be raised to powers
        X_Mat res(m.r, m.c, m.mod); // response matrix (in bin exponentiation we gotta ensure identity matrix to mul with mat)
        for (int i = 0; i < m.r; i++) res.mat[i][i] = 1;
        for (; p; p >>= 1){ // bin exponentiation
            if (p & 1) res *= m;
            m *= m;
        }
        return res;
    }
};
// Double-Ended Priority Queue
class X_DoublePQ{
public:
    multiset<int> pq;
    // O(1) returns size of priority queue
    int size() { return (int)pq.size(); }
    // O(logn) inserts into priority queue
    void insert(int x) { pq.insert(x); }
    // O(1) gets min el
    int min() { return *pq.begin(); }
    // O(1) gets max el
    int max() { return *pq.rbegin(); }
    // O(logn) deletes min el
    void deleteMin() { 
        if (!pq.size()) return;
        pq.erase(pq.begin());
    }
    // O(logn) deletes max el
    void deleteMax() { 
        if (!pq.size()) return;
        auto itr = pq.end(); itr--;
        pq.erase(itr);
    }
};
// DSU
class X_DSU{
public: 
    vector<ll> id;
    vector<ll> size;
    void make_set(ll n){
        id = vector<ll> (n);
        size = vector<ll> (n, 1);
        for (ll i = 0; i < n; i++) id[i] = i;
    }
    void clear_set(){
        for (ll i = 0; i < (ll)id.size(); i++) { id[i] = i; size[i] = 1; }
    }
    ll find_set(ll v){
        if (v == id[v]) return v;
        return id[v] = find_set(id[v]);
    }
    ll total_set(){
        ll total = 0;
        for (ll i = 0; i < (ll)id.size(); i++) total += (i == id[i]) ? 1 : 0;
        return total;
    }
    void union_set(ll u, ll v){
        ll uID = find_set(u), vID = find_set(v);
        if (uID != vID){
            if (size[uID] > size[vID]){
                id[vID] = uID;
                size[uID] += size[vID];
            } else {
                id[uID] = vID;
                size[vID] += size[uID];
            }
        }
    }
};
// Get bitset print of input
bitset<BS> X_bs(ll ip){ return bitset<BS>(ip); }
bitset<BS> X_bs(int ip){ return bitset<BS>(ip); }
// Returns random in [a,b]
int X_rand(int a, int b) { return a + rand() % (b - a + 1); }
// Euclid's gcd algorithm
// $$ TIME: O(log(min(a, b)))
ll X_gcd (ll a, ll b){
    while (b) {
        a %= b;
        swap(a, b);
    }
    return a;
}
// Euclid's extended algorithm, find x,y s.t ax + by = gcd(a,b)
// $$ TIME: O(log(min(a, b)))
ll X_gcd_extended(ll a, ll b, ll& x, ll& y){
    x = 1, y = 0;
    ll x1 = 0, y1 = 1, a1 = a, b1 = b;
    while (b1) {
        ll q = a1 / b1;
        tie(x, x1) = make_tuple(x1, x - q * x1);
        tie(y, y1) = make_tuple(y1, y - q * y1);
        tie(a1, b1) = make_tuple(b1, a1 - q * b1);
    }
    return a1;
}
// Computes the total no of solutions (x,y) for `ax + by = c`, with x1<=x<=x2 and y1<=y<=y2, returns -1 if ~infinite sols
// $$ TIME: O(log(min(a,b)))
ll X_diophantine_total_sols(ll a, ll b, ll c, pair<ll, ll> xRange = {0, LLONG_MAX}, pair<ll, ll> yRange = {0, LLONG_MAX}){
    // checking for any infinity type bound
    bool infInvolved = (xRange.second == LLONG_MAX || yRange.second == LLONG_MAX || xRange.first == LLONG_MIN || yRange.first == LLONG_MIN);
    // PRUNE: Edge Cases
    if (!a && !b && c) return 0;
    else if (!a && !b && !c) return ((infInvolved) ? -1 : (xRange.second - xRange.first + 1) * (yRange.second - yRange.first + 1));
    else if (!a || !b){
        if (!a){
            if (!(c % b) && yRange.first <= (c / b) && (c / b) <= yRange.second) return ((!infInvolved) ? xRange.second - xRange.first + 1 : -1);
            else return 0;
        } else {
            if (!(c % a) && xRange.first <= (c / a) && (c / a) <= xRange.second) return ((!infInvolved) ? yRange.second - yRange.first + 1 : -1);
            else return 0;
        }
    }
    // Getting a single solution
    ll x, y, g;
    g = X_gcd_extended((ll)a, (ll)b, x, y);
    if (c % g) return 0;
    ll x0 = x * (c / g), y0 = y * (c / g);
    double ag = a / g, bg = b / g;
    // Getting range of k for x,y and combined range kZ
    pair<ll, ll> kX, kY, kZ;
    if (kX.first == LLONG_MIN) kX.first = LLONG_MIN; 
    else kX.first = (x0 >= xRange.first) ? -floor((double)(x0 - xRange.first) / abs(bg)) : ceil((double)(xRange.first - x0) / abs(bg));
    if (kY.first == LLONG_MIN) kY.first = LLONG_MIN;
    else kY.first = (y0 >= yRange.first) ? -floor((double)(y0 - yRange.first) / abs(ag)) : ceil((double)(yRange.first - y0) / abs(ag));
    if (xRange.second == LLONG_MAX) kX.second = LLONG_MAX;
    else kX.second = (x0 >= xRange.second) ? -ceil((double)(x0 - xRange.second) / abs(bg)) : floor((double)(xRange.second - x0) / abs(bg));
    if (yRange.second == LLONG_MAX) kY.second = LLONG_MAX;
    else kY.second = (y0 >= yRange.second) ? -ceil((double)(y0 - yRange.second) / abs(ag)) : floor((double)(yRange.second - y0) / abs(ag));
    if (bg < 0) kX = {-kX.second, -kX.first};
    if (ag < 0) kY = {-kY.second, -kY.first};
    kZ = {-kY.second, -kY.first};
    // Prune and return
    if ((kY.first > kY.second) || (kX.first > kX.second)) return 0;
    kZ = {max(kZ.first, kX.first), min(kZ.second, kX.second)};
    return ((kZ.first <= kZ.second) ? kZ.second - kZ.first + 1 : 0);
}
// Computes and returns all primes upto n as a bool array; 
// possible optimizations - see for only odd nos (memory & time halved, done if `ignoreEven`) / see segmented sieve
// $$ TIME: O(n log(log n)); MEMORY [IMP]: O(n)
vector<bool> X_sieve(ll n, bool ignoreEven = false){
    vector<bool> is_prime(n+1, true);
    is_prime[2] = true;
    is_prime[0] = is_prime[1] = false;
    for (int i = 2 + (int)ignoreEven; i * i <= n; i += 1 + (int)ignoreEven) {
        if (is_prime[i]) {
            for (int j = i * i; j <= n; j += i * (1 + (int)ignoreEven)) is_prime[j] = false;
        }
    }
    return is_prime;
}
// Computes only the COUNT of primes upto n; Better than X_sieve on memory - O(sqrt(n)); if `store` is true, primes are stored in `allPrimes`
// $$ TIME: O(n log(log sqrt(n))); MEMORY [IMP]: O(sqrt(n))
ll X_sieve_segmented_count(ll n, vector<ll> &allPrimes, bool store = false) {
    const ll S = 10000; // block/segment size (generally 1e4 - 1e5)
    vector<ll> primes;
    ll nsqrt = sqrt(n);
    vector<char> is_prime(nsqrt + 2, true);
    for (ll i = 2; i <= nsqrt; i++) { // store primes till sqrt(n)
        if (is_prime[i]) {
            primes.push_back(i);
            for (ll j = i * i; j <= nsqrt; j += i) {
                is_prime[j] = false;
            }
        }
    }
    ll result = 0; // total count of primes
    vector<char> block(S);
    for (ll k = 0; k * S <= n; k++) { // mark primes for each block
        fill(block.begin(), block.end(), true);
        ll start = k * S;
        for (ll p : primes) {
            ll start_idx = (start + p - 1) / p;
            ll j = max(start_idx, p) * p - start;
            for (; j < S; j += p)
                block[j] = false;
        }
        if (k == 0) block[0] = block[1] = false;
        for (ll i = 0; i < S && start + i <= n; i++) {
            if (block[i]){
                result++;
                if (store) allPrimes.push_back(start + i); // actual prime no is start+i, store if told
            }
        }
    }
    return result;
}
// Computes and stores bool of array of primes in range [L, R]; Uses segmented Seive
// $$ TIME: O(n log(log sqrt(n))); MEMORY [IMP]: O(sqrt(n)) [n = R - L]
vector<bool> X_sieve_segmented_all(ll L, ll R) {
    // generate all primes up to sqrt(R)
    ll lim = sqrt(R);
    vector<char> mark(lim + 1, false);
    vector<ll> primes;
    for (ll i = 2; i <= lim; ++i) {
        if (!mark[i]) {
            primes.emplace_back(i);
            for (ll j = i * i; j <= lim; j += i){
                mark[j] = true;
            }
        }
    }
    vector<bool> isPrime(R - L + 1, true);
    for (ll i : primes){
        for (ll j = max(i * i, (L + i - 1) / i * i); j <= R; j += i){
            isPrime[j - L] = false;
        }
    }
    if (L == 1) isPrime[0] = false;
    return isPrime;
}
// get prime factors, returns vector of pairs of ll, where first == prime factor, second == it's power
//
// $$ TIME: O(sqrt(N))
vector<pair<ll, ll>> prime_factors_sqrt(ll N){
    ll prime = 2, n = N;
    vector<pair<ll, ll>> res(0);
    while (prime * prime <= n){
        if (N % prime == 0) {
            ll count = 0;
            while (N % prime == 0) { N /= prime; count++; }
            res.push_back({prime, count});
        }
        prime++;
    }
    return res;
}
// get prime factors, returns vector of pairs of ll, where first == prime factor, second == it's power
//
// $$ TIME: O(log(N)) for composite N; O(N) for prime N
vector<pair<ll, ll>> prime_factors_sieve(ll N){
    ll prime = 2;
    vector<pair<ll, ll>> res(0);
    while (N > 1){
        if (N % prime == 0) {
            ll count = 0;
            while (N % prime == 0) { N /= prime; count++; }
            res.push_back({prime, count});
        }
        prime++;
    }
    return res;
}
// Euler's Totient Function - gives no of nos less than x which are coprime with n
//
// $$ TIME: O(sqrt(N) * log(N)) for composite N; O(N) for prime N
ll phi(ll N){
    ll prime = 2, n = N;
    float res = n;
    while (prime * prime <= n){
        if (N % prime == 0){
            while (N % prime == 0){ N /= prime; }
            res *= (1.0 - (1.0 / (float)prime)); // or res -= res / prime
        }
        prime++;
    }
    if (N > 1) { res *= (1.0 - (1.0 / (float)N)); } // or res -= res/N
    return (ll)res;
}
// Computes factorials from last highest previously precomputed factorial to currently asked and all in between.
// $$ TIME: Depends on last precomputed factorial and current number (O(N))
ll X_factorial_mod(ll n, ll m){
	if (n+1>(ll)FACTORIALS.size() && FACTORIALS.size()!=0){
		ll p = FACTORIALS[FACTORIALS.size()-1];
		//FACTORIALS.push_back(p);
		ll i=FACTORIALS.size();
		for(; i<=n; i++) {
			p = (p * i) % m;
			FACTORIALS.push_back(p);
		}
		return p;
	}
	else if (FACTORIALS.size()==0){
		ll p = 1;
		FACTORIALS.push_back(p);
		ll i=FACTORIALS.size();
		for(; i<=n; i++) {
			p = (p * i) % m;
			FACTORIALS.push_back(p);
		}
		return p;
	}
	else {
		return FACTORIALS[n];
	}
}
// Computes a^b efficiently
// $$ TIME: O(log(b))
ll X_power(ll a, ll b){
	if (b == 0) return 1;
	ll res = X_power(a, b/2);
    return (b % 2) ? res * res * a : res * res;
}
// Computes a^b efficiently while keeping answer mod m
// $$ TIME: O(log(b))
ll X_power_mod(ll a, ll b, ll m = LLONG_MAX){
	if (b == 0){ return 1; }
	ll res = X_power_mod(a, b/2, m) % m;
	res = (res * res) % m;
	if (b % 2){
		return (res * a) % m;
	} else {
		return res;
	}
}
// Computes mod inverse of a wrt m, i.e a^-1 mod m; using euclid's extended algorithm; CONDITION: a,m to be coprime
// $$ TIME: O(log(min(a, m))) [NOTE: returns -1 if inverse doesn't exist!]
ll X_mod_inverse(ll a, ll m){
    ll x, y, res;
    ll g = X_gcd_extended(a, m, x, y);
    if (g != 1){
        cout << "Inverse doesn't exist! A and M are not coprime!";
		res = -1;
	} else {
        res = (x % m + m) % m; // m is added to handle negative x
    }
	return res;
}
// uses fermat's little theorum for computing mod inverse of a wrt m; states that a^-1 mod m = a^(m-2) mod m; CONDITION: m to be prime
// $$ TIME: O(log(m))
ll X_mod_inverse_fermat(ll a, ll m){
	//     ll g = X_gcd(a, m);
	//     if (g != 1){
	//         cout << "Inverse doesn't exist! A and M are not coprime!";
	// 	return -1;
	// } else {
	// 	return X_power_mod(a, m - 2, m);
	//     }
    return X_power_mod(a, m - 2, m);
}
// Computes (a / b) mod m; mod inverse of b needs to exist with m (i.e gcd(b,m)=1), else -1 is returned
// $$ TIME: O(log(b))
ll X_mod_division(ll a, ll b, ll m){
    ll inverse = X_mod_inverse(b, m);
    if (inverse == -1) return -1;
    ll modDiv = ((a % m) * inverse) % m;
    if (modDiv < 0) modDiv += m;
    return modDiv;
}
// computes nCr while keeping answer mod m; by computing n!, and mod inverses of r!, (n-1)!
// $$ TIME: O(N) : O(N) for precomputing factorials till n; 2*O(log(m)) for computing 2 mod inverses
ll nCr_mod(ll n, ll r, ll m) {
	ll p = ((X_factorial_mod(n, m) * X_mod_inverse(FACTORIALS[r], m)) % m * X_mod_inverse(FACTORIALS[n-r], m)) % m;
	return p;
}
/////////////////////////////////////////////// END ///////////////////////////////////////////////

/////////////////////////////////////////////// DRIVER CODE ///////////////////////////////////////////////
#ifndef ONLINE_JUDGE
    clock_t tStart = clock();
#endif
void start(); // cpp programs
void generate(int argc, char* argv[]); // generator for stress testing
void computeRuntime(){
    #ifndef ONLINE_JUDGE
        fprintf(stderr, "\n>>> [@mohitdmak]: !OJ_mode: Runtime: %.6fs <<<\n", (double) (clock() - tStart) / CLOCKS_PER_SEC);
    #endif
}
int main(int argc, char* argv[]){
	ios_base::sync_with_stdio(false);
	cin.tie(NULL) ; cout.tie(NULL);
	// cout.precision(numeric_limits<double>::max_digits10);
    #ifndef ONLINE_JUDGE
        rlimit R;
        getrlimit(RLIMIT_STACK, &R);
        R.rlim_cur = R.rlim_max;
        setrlimit(RLIMIT_STACK, &R);
    #endif
    #ifndef MOHITDMAK_GENERATOR_MODE // flagged within generator
        start();
    #else
        generate(argc, argv); 
    #endif
    #ifndef ONLINE_JUDGE
        #ifndef MOHITDMAK_STRESS_TESTING_MODE // flagged within counter brutes
            computeRuntime();
        #endif
    #endif
	return (0) ;
}
/////////////////////////////////////////////// END ///////////////////////////////////////////////

int n, m, h[200001];

void solve(){
    // error(n, m);
    // for (int i = 0; i <= n; i++) error(i, h[i]);
    auto cmp = [](int i, int j){ return h[i] - m * i > h[j] - m * j; };
    multiset<int, decltype(cmp)> dp(cmp);
    for (int i = 1; i <= n; i++){
        if (h[i] > m * i) continue;
        auto itr = dp.upper_bound(i);
        // error(i, h[i], dp, itr==dp.end());
        if (itr == dp.end()) dp.insert(i);
        else dp.erase(itr), dp.insert(i);
    }
    cout << n - dp.size();
}
 
void start(){
    cin >> n >> m; int i = 0; while (i++ < n) cin >> h[i];
    solve();
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...