Submission #1130898

#TimeUsernameProblemLanguageResultExecution timeMemory
113089879brue서열 (APIO23_sequence)C++20
100 / 100
1086 ms93876 KiB
#include "sequence.h"
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int INF = 1e9;

struct Node{
    int sum, prf, suf;
    Node(){}
    Node(int sum, int prf, int suf): sum(sum), prf(prf), suf(suf){}
    Node(int x){
        sum = x;
        prf = suf = max(x, 0);
    }

    Node operator+(const Node &r)const{
        return Node(sum + r.sum, max(prf, sum + r.prf), max(suf + r.sum, r.suf));
    }
};

struct segTree{
    Node tree[1<<20];

    void init(int i, int l, int r, int v){
        if(l==r){
            tree[i] = Node(v);
            return;
        }
        int m = (l+r)>>1;
        init(i*2, l, m, v);
        init(i*2+1, m+1, r, v);
        tree[i] = tree[i*2] + tree[i*2+1];
    }

    void update(int i, int l, int r, int x, int v){
        if(l==r){
            tree[i] = Node(v);
            return;
        }
        int m = (l+r)>>1;
        if(x<=m) update(i*2, l, m, x, v);
        else update(i*2+1, m+1, r, x, v);
        tree[i] = tree[i*2] + tree[i*2+1];
    }

    Node query(int i, int l, int r, int s, int e){
        if(r<s || e<l) return Node(0, 0, 0);
        if(s<=l && r<=e) return tree[i];
        int m = (l+r)>>1;
        return query(i*2, l, m, s, e) + query(i*2+1, m+1, r, s, e);
    }
} treeMax, treeMin; /// +0-, -0+

struct minTree{
    int tree[1<<21];

    void init(int i, int l, int r){
        tree[i] = INF;
        if(l==r) return;
        int m = (l+r)>>1;
        init(i*2, l, m);
        init(i*2+1, m+1, r);
    }

    void update(int i, int l, int r, int x, int v){
        if(l==r){
            tree[i] = min(tree[i], v);
            return;
        }
        int m = (l+r)>>1;
        if(x<=m) update(i*2, l, m, x, v);
        else update(i*2+1, m+1, r, x, v);
        tree[i] = min(tree[i*2], tree[i*2+1]);
    }

    int query(int i, int l, int r, int s, int e){
        if(r<s || e<l) return INF;
        if(s<=l && r<=e) return tree[i];
        int m = (l+r)>>1;
        return min(query(i*2, l, m, s, e), query(i*2+1, m+1, r, s, e));
    }
} tree;

int n;

void update_zero(int x){
    treeMax.update(1, 1, n, x, 0);
    treeMin.update(1, 1, n, x, 0);
}

void update_one(int x){
    treeMax.update(1, 1, n, x, -1);
    treeMin.update(1, 1, n, x, 1);
}

int arr[500002];
vector<int> occ[500002];

int loc[500002];
int prf1[500002], suf1[500002], btw1[500002];
int prf2[500002], suf2[500002], btw2[500002];
int S1[500002], T1[500002];
int S2[500002], T2[500002];

bool able(int L, int k){
    int sum1 = 0, sum2 = 0;
    for(int i=1; i<=L-2; i++) sum1 += btw1[i], sum2 += btw2[i];

    for(int s=1; s+L-1 <= k; s++){
        int e = s+L-1;
        sum1 += btw1[e-1] - btw1[s-1], sum2 += btw2[e-1] - btw2[s-1];
        int v1 = sum1 + suf1[s] + prf1[e], v2 = sum2 + suf2[s] + prf2[e];
        if(v1 >= -L && v2 >= -L) return true;
    }
    return false;
}

struct Query{
    int x, y, idx, type;
    Query(){}
    Query(int x, int y, int idx, int type): x(x), y(y), idx(idx), type(type){}

    bool operator<(const Query &r)const{
        if(y!=r.y) return y<r.y;
        if(type!=r.type) return type<r.type;
        return x<r.x;
    }
};

int sequence(int _N, vector<int> A){
    n = _N;
    for(int i=1; i<=n; i++){
        arr[i] = A[i-1];
        occ[arr[i]].push_back(i);
    }
    treeMax.init(1, 1, n, 1), treeMin.init(1, 1, n, -1);

    int ans = 1;

    for(int v=1; v<=n; v++){
        if(occ[v].empty()) continue;

        int k = (int)occ[v].size();
        for(int i=1; i<=k; i++) loc[i] = occ[v][i-1];
        loc[0] = 0, loc[k+1] = n+1;

        for(int i=1; i<=k; i++) update_zero(loc[i]);

        for(int i=0; i<=k; i++){
            int s = loc[i]+1, e = loc[i+1]-1;
            Node p1 = treeMax.query(1, 1, n, s, e), p2 = treeMin.query(1, 1, n, s, e);
            if(i) prf1[i] = p1.prf, prf2[i] = p2.prf;
            if(i<k) suf1[i+1] = p1.suf, suf2[i+1] = p2.suf;
            if(i && i<k) btw1[i+1] = btw1[i] + p1.sum + 1, btw2[i+1] = btw2[i] + p2.sum + 1;
        }

        for(int i=1; i<=k; i++){
            S1[i] = btw1[i] - suf1[i], S2[i] = btw2[i] - suf2[i];
            T1[i] = btw1[i] + prf1[i] + 1, T2[i] = btw2[i] + prf2[i] + 1;
        }

        /// (S1, S2) <= (T1, T2)인 점 찾기
        vector<int> xVal, yVal;
        for(int i=1; i<=k; i++){
            xVal.push_back(S1[i]), xVal.push_back(T1[i]);
            yVal.push_back(S2[i]), yVal.push_back(T2[i]);
        }
        sort(xVal.begin(), xVal.end());
        sort(yVal.begin(), yVal.end());
        xVal.erase(unique(xVal.begin(), xVal.end()), xVal.end());
        yVal.erase(unique(yVal.begin(), yVal.end()), yVal.end());

        int X = (int)xVal.size();
        for(int i=1; i<=k; i++){
            S1[i] = lower_bound(xVal.begin(), xVal.end(), S1[i]) - xVal.begin() + 1;
            T1[i] = lower_bound(xVal.begin(), xVal.end(), T1[i]) - xVal.begin() + 1;
            S2[i] = lower_bound(yVal.begin(), yVal.end(), S2[i]) - yVal.begin() + 1;
            T2[i] = lower_bound(yVal.begin(), yVal.end(), T2[i]) - yVal.begin() + 1;
        }

        vector<Query> vec;
        for(int i=1; i<=k; i++){
            vec.push_back(Query(S1[i], S2[i], i, 0));
            vec.push_back(Query(T1[i], T2[i], i, 1));
        }
        sort(vec.begin(), vec.end());

        tree.init(1, 1, X);
        for(Query &p: vec){
            if(p.type == 0) tree.update(1, 1, X, p.x, p.idx);
            else ans = max(ans, p.idx - tree.query(1, 1, X, 1, p.x) + 1);
        }

        for(int i=1; i<=k; i++) update_one(loc[i]);
    }

    return ans;
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...