Submission #1369115

#TimeUsernameProblemLanguageResultExecution timeMemory
1369115KALARRYSequence (APIO23_sequence)C++20
100 / 100
971 ms39660 KiB
//chockolateman

#include<bits/stdc++.h>
#include "sequence.h"

using namespace std;

int n,a[500005],b[500005],preff[500005];
pair<int,int> temp[500005];

struct Node
{
    int maxim,minim,lazy = 0;
} st[2000005];

Node combine(Node left,Node right)
{
    Node ret;
    ret.maxim = max(left.maxim,right.maxim);
    ret.minim = min(left.minim,right.minim);
    return ret;
}

void build(int v = 1,int start = 0,int end = n)
{
    if(start==end)
    {
        preff[start] = -start;
        st[v].maxim = preff[start];
        st[v].minim = preff[start];
        return;
    }
    int mid = (start + end)/2;
    build(2*v,start,mid);
    build(2*v+1,mid+1,end);
    st[v] = combine(st[2*v],st[2*v+1]);
}

void propagate(int v,int start,int end);

void update(int l,int r,int val,int v = 1,int start = 0,int end = n)
{
    if(start==l && end==r)
    {
        st[v].maxim += val;
        st[v].minim += val;
        st[v].lazy += val;
        if(start==end)
            preff[start] += val;
        return;
    }
    propagate(v,start,end);
    int mid = (start + end)/2;
    if(r <= mid)
        update(l,r,val,2*v,start,mid);
    else if(l > mid)
        update(l,r,val,2*v+1,mid+1,end);
    else
    {
        update(l,mid,val,2*v,start,mid);
        update(mid+1,r,val,2*v+1,mid+1,end);
    }
    st[v] = combine(st[2*v],st[2*v+1]);
}

void propagate(int v,int start,int end)
{
    if(st[v].lazy)
    {
        int mid = (start + end)/2;
        update(start,mid,st[v].lazy,2*v,start,mid);
        update(mid+1,end,st[v].lazy,2*v+1,mid+1,end);
        st[v].lazy = 0;
    }
}

Node query(int l,int r,int v = 1,int start = 0,int end = n)
{
    if(start==l && end==r)
        return st[v];
    propagate(v,start,end);
    int mid = (start + end)/2;
    if(r <= mid)
        return query(l,r,2*v,start,mid);
    else if(l > mid)
        return query(l,r,2*v+1,mid+1,end);
    else
        return combine(query(l,mid,2*v,start,mid),query(mid+1,r,2*v+1,mid+1,end));
}

bool intersect(int i,int j,int x,int y)
{
    return i <= y && j >= x;
}

int find_rightest(int l,int r,int v = 1,int start = 0,int end = n)
{
    if(start==end)
        return start;
    propagate(v,start,end);
    int mid = (start + end)/2;
    if(intersect(l,r,st[2*v+1].minim,st[2*v+1].maxim))
        return find_rightest(l,r,2*v+1,mid+1,end);
    else
        return find_rightest(l,r,2*v,start,mid);
}

int find_leftest(int l,int r,int v = 1,int start = 0,int end = n)
{
    if(start==end)
        return start;
    propagate(v,start,end);
    int mid = (start + end)/2;
    if(intersect(l,r,st[2*v].minim,st[2*v].maxim))
        return find_leftest(l,r,2*v,start,mid);
    else
        return find_leftest(l,r,2*v+1,mid+1,end);
}

int sequence(int N, std::vector<int> A) {
    n = N;
    for(int i = 1 ; i <= N ; i++)
    {
        a[i] = A[i-1];
        b[i] = a[i];
        temp[i] = {a[i],i};
    }
    sort(b+1,b+N+1);
    int med = (N+1)/2;
    int ans = 0;
    int cnt = 0;
    for(int i = 1 ; i <= N ; i++)
        if(b[i]==b[med])
            cnt++;
    ans = cnt;
    cnt = 0;
    med = (N+2)/2;
    for(int i = 1 ; i <= N ; i++)
        if(b[i]==b[med])
            cnt++;
    ans = max(ans,cnt);
    sort(temp+1,temp+N+1);
    build();
    int r = 1;
    int l = 1;
    vector<int> poses;
    while(l < N)
    {
        r = l;
        while(r < N && temp[r+1].first == temp[l].first)
            r++;
        int prv = 0;
        for(int i = l ; i <= r ; i++)
            poses.push_back(temp[i].second);
        
        // //Case 1: First emf being the median
        for(int i,k = 0 ; k < (r-l+1) ; k++)
        {
            i = poses[k];
            update(i,N,1);
            Node front = query(prv,i-1);
            int reach = find_rightest(front.minim - 1,front.maxim + 1);
            cnt = upper_bound(poses.begin(),poses.end(),reach) - poses.begin() - k;
            ans = max(ans,cnt);
            update(i,N,1);
            prv = i;
        }
        
        int nxt = N+1;
        //Case 2: First emf being the median
        for(int i,k = (r-l) ; k >= 0 ; k--)
        {
            i = poses[k];
            update(i,N,-1);
            Node back = query(i,nxt-1);
            int reach = find_leftest(back.minim - 1,back.maxim + 1) + 1;
            cnt =  k - (lower_bound(poses.begin(),poses.end(),reach) - poses.begin()) + 1;
            ans = max(ans,cnt);
            update(i,N,-1);
            nxt = i;
        }

        for(auto i : poses)
            update(i,N,2);
        poses.clear();
        l = r+1;
    }
    return ans;
}
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...
#Result Execution timeMemoryGrader output
Fetching results...