Submission #1256943

#TimeUsernameProblemLanguageResultExecution timeMemory
1256943nguyenhuythachExam (eJOI20_exam)C++20
88 / 100
1097 ms52908 KiB
#include<bits/stdc++.h>
#include<algorithm>
#include<random>
#include<chrono>
#include<cstdlib>
#include<ctime>
#include<numeric>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<queue>
#include<iomanip>
#define int long long
#define ll long long
#define fi first
#define se second
#define pii pair<int,int>
#define sz(a) ((int)a.size())
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define REP(i,k,j) for(int i=k;i>=j;i--)
#define FORD(i,a) for(auto i:a)
#define rngdcl mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count())
#define random(l,r) ((l)+(rng()%(r-l+1)))
using namespace std;
const int nmax=5e5+1;
int n,crr=0;
int a[nmax],b[nmax];
map<int,int> mp;
set<int> s;
int L[nmax]; // log floor

// sparse table stored dynamically to avoid huge static allocation
vector<vector<int>> mn; // not really used but keep for parity
vector<vector<int>> mx;

int getmax(int x, int y)
{
    if(x>y) swap(x,y);
    int len = y - x + 1;
    int LOG = L[len];
    return max(mx[x][LOG], mx[y-(1<<LOG)+1][LOG]);
}

void build()
{
    // compute logs
    L[1] = 0;
    for(int i=2;i<=n;i++) L[i]=L[i/2]+1;

    int maxLog = L[n];
    // allocate sparse table: indices 1..n, logs 0..maxLog
    mx.assign(n+1, vector<int>(maxLog+1, 0));
    mn.assign(n+1, vector<int>(maxLog+1, 0)); // kept if needed later

    for(int i=1;i<=n;i++) // base case
    {
        mn[i][0]=a[i];
        mx[i][0]=a[i];
    }
    for(int j=1;j<=maxLog;j++)
    {
        for (int i = 1; i + (1<<j) - 1 <= n; ++i)
        {
            mx[i][j]=max(mx[i][j-1],mx[i+(1<<(j-1))][j-1]);
            mn[i][j]=min(mn[i][j-1],mn[i+(1<<(j-1))][j-1]);
        }
    }
}

struct BIT
{
    vector<int> tree;
    int n;
    
    BIT (int N=0)
    {
        n=N;
        tree.assign(n+5,0);
    }
    
    void update(int x,int val) {while(x<=n) { tree[x]=max(tree[x],val); x+=(x&-x);} }
    int get(int x) { int ans=0; while(x>0) {ans=max(ans,tree[x]); x-=(x&-x);} return ans; }
};

void input()
{
    cin >> n;
    FOR(i,1,n) cin >> a[i];
    FOR(i,1,n) cin >> b[i];
    FOR(i,1,n) s.insert(a[i]);
    // map values in increasing order (1-based ranks)
    FORD(val, s) mp[val]=++crr;
    FOR(i,1,n)
    {
        a[i]=mp[a[i]];
        if(mp.count(b[i])) b[i]=mp[b[i]];
        else b[i]=0;
    }
}

signed main()
{
    ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    input();

    // allocate pos according to compressed size
    vector<vector<int>> pos(crr+1);
    FOR(i,1,n) pos[a[i]].push_back(i);

    build();

    BIT bit(n); // sized by n
    vector<pair<int,int>> ops;
    // collect ops in same order as original logic: for each i in B, push valid positions of that value (right->left)
    FOR(i,1,n)
    {
        if(!b[i]) continue;
        for(int j = (int)pos[b[i]].size()-1; j>=0; --j)
        {
            int id = pos[b[i]][j];
            if(getmax(id,i) > b[i]) continue;
            int pre = bit.get(id);
            bit.update(id, pre+1);
        }
    }
    cout << bit.get(n) << '\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...