Submission #1164934

#TimeUsernameProblemLanguageResultExecution timeMemory
1164934sergiogzzSateliti (COCI20_satellti)C++20
110 / 110
348 ms68476 KiB
/*
g++ -std=gnu++20 cf2028.cpp -o cf2028 && ./cf2028 < input.txt > output.txt
*/

#include <vector>
#include <iostream>
#include <unordered_map>
#include <unordered_set>
#include <map>
#include <algorithm>
#include <deque>
#include <stack>
#include <set>
#include <math.h>
#include <queue>
#include <cmath>
#include <numeric>
#include <complex>
#include <chrono>
#include <random>
#include <assert.h>
#include <iomanip>
// #include <bits/stdc++.h>


using namespace std;

namespace macros {

    bool printDebug = 0;

    template<typename T>
    void print(T arg) {
        if (!printDebug) return; 
        cout << arg;
    }

    template<typename T, typename... Args>
    void print(T first, Args... args) {
        if (!printDebug) return;
        cout << first << " ";
        print(args...);
    }
    
    // # define M_PI 3.14159265358979323846
    #define optimiza_io \
        cin.tie(0);     \
        ios_base::sync_with_stdio(0);
    #define ll long long
    #define ld double
    #define pb push_back
    #define eb emplace_back
    #define pi pair<ll, ll>
    #define f first
    #define s second
    #define rep(i, a, b) for (ll i = (a); i < (b); i++)
    #define repi(i, a, b) for (ll i = (a); i >= (b); i--)
    #define trav(a, x) for (auto &(a) : (x))
    #define endl "\n"
    #define vi vector<ll>
    #define vvi vector<vi>
    #define vpi vector<pi>
    #define vs vector<string>
    #define sz(a) ((ll)(a).size())
    #define ldd(a) ((ld)(a))
    #define mp(a, b) make_pair((a), (b))
    #define minn(a, b) (a) = min ((a), (b))
    #define maxx(a, b) (a) = max ((a), (b))
    #define all(x) (x).begin(), (x).end()
    #define popcount(x) (ll)__builtin_popcount((x))
    const ld EPS = 1e-7;
    typedef long long C;    
    typedef complex<C> P;
    #define X real()
    #define Y imag()


    template<typename T>
    void printVec(vector<T> arr) {
        trav(u, arr) {
            print(u, " ");
        }
        print(endl);
    }

    // check if 2 ld are equal
    bool equal_ld(ld a, ld b) {
        return abs(a-b) < EPS;
    }
    // for xor hashing
    ll rng(const ll most = INT64_MAX) {
        static mt19937 gen(chrono::steady_clock::now().time_since_epoch().count());
        return uniform_int_distribution<ll>(0, most)(gen);
    }

    void modulate(ll &x, const ll &mod) {
        x %= mod;
        x += mod;
        x %= mod;
    }
}
const ll INF = 1e6;
// const ll mod = 1e9+7;
const ll mod = 998244353;
const ll maxn = 3e5+10;

using namespace macros;


// solve
struct HashedString {
    // change M and B if you want
    static const long long M = 1e9 + 9;
    static long long B;

    // pow[i] contains B^i % M
    static vector<long long> pow;

    // p_hash[i] is the hash of the first i characters of the given string
    vector<long long> p_hash;

    // can be vi too
    HashedString(const string &s) : p_hash(s.size() + 1) {
        while (pow.size() <= s.size()) { pow.push_back((pow.back() * B) % M); }

        p_hash[0] = 0;
        for (int i = 0; i < s.size(); i++) {
            p_hash[i + 1] = ((p_hash[i] * B) % M + s[i]) % M;
        }
    }

    HashedString(const vi &s) : p_hash(s.size() + 1) {
        while (pow.size() <= s.size()) { pow.push_back((pow.back() * B) % M); }

        p_hash[0] = 0;
        for (int i = 0; i < s.size(); i++) {
            p_hash[i + 1] = ((p_hash[i] * B) % M + s[i]) % M;
        }
    }

    // r inclusive
    long long get_hash(int start, int end) {
        long long raw_val = (p_hash[end + 1] - (p_hash[start] * pow[end - start + 1]));
        return (raw_val % M + M) % M;
    }
};

long long HashedString::B = rng(HashedString::M - 1);
vector<long long> HashedString::pow = {1};


void solve() {
    ll n, m;
    cin >> n >> m;
    vs mat(n);
    trav(u, mat) {
        cin >> u;
        u += u;
    }

    rep(i, 0, n) {
        mat.pb(mat[i]);
    }

    vector<HashedString> ha, haCols;
    vvi cols(m, vi(2*n)); // transposed

    for (auto u : mat) {
        ha.emplace_back(u);
    }

    // start j
    rep(j, 0, m) {
        rep(i, 0, 2*n) {
            cols[j][i] = ha[i].get_hash(j, j+m-1); 
        }
    }

    rep(j, 0, m) {
        haCols.emplace_back(cols[j]);
    }
    pi ans = mp(0,0);

    auto getHashCols = [&] (pi &dir, ll mid) {
        return haCols[dir.s].get_hash(dir.f , dir.f + mid);
    };

    auto getHash = [&] (pi &dir, ll difRow, ll mid) {
        return ha[dir.f + difRow].get_hash(dir.s , dir.s + mid);
    };

    auto check = [&] (pi curr) {
        
        // BS over colums, find first diff
        ll l = 0, r = n-1, mid;
        ll difRow = n;

        while (l <= r) {
            mid = (r-l) / 2 + l;
            print("l = ", l, " ");
            print("r = ", r, " ");
            print("mid = ", mid, " ", endl);
            if (getHashCols(ans, mid) == getHashCols(curr, mid)) {
                l = mid+1;
                print(" - equal", endl);
            } else {
                minn(difRow, mid);
                print(" - dif, interesting", endl);
                r = mid-1;
            }
        }
        print("got", difRow, endl);

        if (difRow == n) return false;

        print(endl, "---", endl);
        l = 0, r = m-1;
        ll difCol = m;
        while (l <= r) {
            mid = (r-l) / 2 + l;
            print("l = ", l, " ");
            print("r = ", r, " ");
            print("mid = ", mid, " ", endl);
            if (getHash(ans, difRow, mid) == getHash(curr, difRow, mid)) {
                l = mid+1;
                print(" - equal", endl);
            } else {
                minn(difCol, mid);
                print(" - dif, interesting", endl);
                r = mid-1;
            }
        }

        if (difCol == m) return false;

        bool result = (
            mat[curr.f + difRow][curr.s + difCol]
            <
            mat[ans.f + difRow][ans.s + difCol]
        );
        print("result = ", result, endl);
        return result;
    };

    rep(i, 0, n) {
        rep(j, 0, m) {
            if (i == j && i == 0) continue; // first assumed to be smaller
            print(i, j, ": ", endl);
            if (check(mp(i, j))) {
                ans = mp(i, j);
            }

            print(endl," ..-.-.-.-   ", endl, endl);
        }
    }

    rep(i, 0, n) {
        rep(j, 0, m) {
            cout << mat[i + ans.f][j + ans.s];
        }
        cout << endl;
    }
}
//

/*
    NEW ME: 
    - Read test cases and experiment with them, use your page 2!!!
    - Ask questions. What to do to achieve this? What's different from usual slower X strat?
    - And ofc, observations
    - Long, Unnecesary coding is not needed!

    ALWAYS REMEMBER:
    - Focus on the target at hand! ---- Making observations? Making formula for X? Write your target down!
    - Simplify before coding
    - Check all test cases!
    - Divide problema dificil en problemas pequeños. POR PARTES!
    - OBSERVATIONS: Recuerda el significado de su nombre
    - EDGE CASES: Yes
    - Calm down

    - Sometimes try formulazo. Intenta representar el valor de manera matemática at some point.
        - Luego intenta derivar formula o simplificarla, ya de ahí tal vez ya queda el problema
        - Formulazo o upper limits!
    - for debugging, read code first before just printing everything haha
    - Even if you find a solution, is the process you made necessary? Is there a way to simplify the process or omit some steps?
    - If greedy, really check if you cannot phantom a possible edge case where it is out of your control
    - Write down the formulas better to facilitate coding
    - primero itera los bits en bitmasking!
    - Si quiero hacer greedy, piensa en "cuando es que me conviene hacer x?"

    OTHER
    - its doable
    - link your ideas, dont forget them
    - remember key aspects, think of even more, optimal

*/


signed main() {
    optimiza_io

    bool file = 0;
    if (file) {
        freopen("lightsout.in", "r", stdin);
        freopen("lightsout.out", "w", stdout);
    }

    bool multipleTestCases = 0;
    printDebug = 0;

    int t = 1;
    if (multipleTestCases) {
        cin >> t;
    }

    rep(i, 0, t) {
        print("\n---------------------\n");
        solve();
    }
}

Compilation message (stderr)

Main.cpp: In function 'int main()':
Main.cpp:305:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  305 |         freopen("lightsout.in", "r", stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:306:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  306 |         freopen("lightsout.out", "w", stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...