Güclü vəzifə#12240

Güclü vəzifə (Həll təhlili)

Tapşırığın müəllifi:

Andriy Xolod (Connect)

Hazırlayan:

Andriy Xolod (Connect)

İzah:

Andriy Xolod (Connect)

Həll

Əvvəlcə qeyd edək ki, əgər biz hər hansı bir mövqedə a_i = b_i edə bilmişiksə, onda bütün j < i üçün də a_j = b_j edə bilərik. Deməli, məsələ elə bir ən böyük tapmaqdan ibarətdir ki, biz a_i = b_i edə bilək.

Həmçinin qeyd edək ki, birinci və ikinci tip əməliyyatlar tətbiq edildikdə, hər hansı bir indeks üçün a_{i-1} - (i-1) ifadəsi a_i - i ifadəsinə bərabər olur. Eyni qayda ilə massivi üçün də bu doğrudur, çünki (a_i - 1) - (i - 1) = a_i - i. Üçüncü tip əməliyyat tətbiq edildikdə isə, silinən indeks -dən böyük olan bütün üçün a_j - j və b_j - j dəyərləri bir vahid azalır.

Beləliklə, məsələ aşağıdakına çevrilir: hər bir üçün massivinin sufiiksi [i+1, |b|] daxilində elə bir indeks varmı ki, a_i - i = b_j - j bərabərliyi yerinə yetsin? Həmçinin, sufiiks [i+2, |b|] daxilində elə bir indeks varmı ki, a_i - i = b_j - j + 1 bərabərliyi doğru olsun? Eyni məntiq massivi üçün də keçərlidir.

Bunu set və ya map strukturlarından istifadə etməklə həyata keçirmək olar.

Bu həllin asimptotik mürəkkəbliyi O(n \times \log n)-dir.

#include <bits/stdc++.h>

// fast_pragmas

//#pragma GCC optimize("O3")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize ("unroll-loops")
//#pragma GCC target("avx,avx2,tune=native")

// fast_pragmas ended

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast")
//#pragma GCC optimize("O3,unroll-loops")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
//#pragma GCC target("avx2,bmi,bmi2,popcnt,lzcnt")

using namespace std;

#define ull unsigned long long
#define ll long long
#define ld long double
#define speed ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define endl '\n'
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
#define pb push_back
#define ln log
#define lg log10
#define log log2
#define here cout<<"HERE"<<endl

const ll clasik = 2e5+7;
const ll mln = 1e6+7;
const ll mod = 1e9+7;
//const ll mod = 998244353;
const ll block_size = 450;
const ll INF = 1e17;

ll df[clasik];

ll a[clasik], b[clasik];

void solve() {

    ll n;
    cin >> n;

    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        a[i] = a[i] - i;
    }

    for (int i = 1; i <= n; i++) {
        cin >> b[i];
        b[i] = b[i] - i;
    }

    set<ll> st1, st2;

    for (int i = n; i >= 1; i--) {
        
        if (a[i] == b[i]) {
            cout << i << endl;
            return;
        }
        if (i == n) continue;

        if (st2.count(a[i]) || a[i] == b[i+1]) {
            cout << i << endl;
            return;
        }
        if (st1.count(b[i]) || b[i] == a[i+1]) {
            cout << i << endl;
            return;
        }
        if (st2.count(a[i] - 1)) {
            cout << i << endl;
            return;
        }
        if (st1.count(b[i] - 1)) {
            cout << i << endl;
            return;
        }

        st1.insert(a[i+1]);
        st2.insert(b[i+1]);
    }

    cout << 0 << endl;
}

signed main() {
    speed;
    int test = 1;
    for (int tt = 1; tt <= test; tt++) {
        solve();
    }
    return 0;
}