제출 #1367561

#제출 시각아이디문제언어결과실행 시간메모리
1367561Lemser서열 (APIO23_sequence)C++20
11 / 100
2100 ms221960 KiB
#include "sequence.h"

#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC optimize("O3")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("avx2")
#pragma GCC target("popcnt")
using namespace std;
 
using ll = long long;
using ull = unsigned long long;
using lld = long double;
using ii = pair<int,int>;
using pll = pair<ll, ll>;
 
using vi = vector<int>;
using vll = vector<ll>;
using vii = vector<ii>;
using vpll = vector<pll>;
using vlld = vector<lld>;
 
#define all(x) x.begin(),x.end()
#define lsb(x) x&(-x)
#define gcd(a,b) __gcd(a,b)
#define sz(x) (int)x.size()
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define fls cout.flush()
 
#define fore(i, l, r) for (ll i = l; i < r; i++)
#define fo(i, n) fore (i, 0, n)
#define forex(i, r, l) for (ll i = r-1; i >= l; i--)
#define ffo(i, n) forex (i, n, 0)
 
bool cmin(ll &a, ll b) { if (b < a) { a=b; return 1; } return 0; }
bool cmax(ll &a, ll b) { if (b > a) { a=b; return 1; } return 0; }


const int INF = 1e18 + 7;

struct SegTreeLazy {

    vector<array<ll, 2>> mn, mx;
	vll lz;
    ll n;
    
    SegTreeLazy () {  }
    SegTreeLazy (ll n): n(n), mn(4*n+4, {0, 0}), mx(4*n+4, {0, 0}), lz(4*n+4, 0) {  }

	void build (ll id, ll l, ll r) {
		if (l==r) {
			mn[id] = {0, l};
			mx[id] = {0, l};
			return;
		}
		ll m = (l+r)/2;
		build(id*2, l, m);
		build(id*2+1, m+1, r);
	}

    void push(ll id,ll l,ll r){
        mn[id][0]+=lz[id];
		mx[id][0]+=lz[id];
        if(l!=r){
            lz[id*2]+=lz[id];
            lz[id*2+1]+=lz[id];
        }
        lz[id]=0;
    }

    void update(ll l, ll r, ll x){update(1,0,n-1,l,r, x);}
    void update(ll id,ll l,ll r,ll i,ll j,ll x){
        push(id,l,r);
        if(l>j||r<i)return;
        if(l>=i&&r<=j){
            lz[id]+=x;
            push(id,l,r);
            return;
        }
        ll m=(l+r)/2;
        update(id*2,l,m,i,j,x);
        update(id*2+1,m+1,r,i,j,x);
        mn[id]=min(mn[id*2],mn[id*2+1]);
        mx[id]=max(mx[id*2],mx[id*2+1]);
    }

    array<ll, 2> querymn(ll l, ll r){return querymn(1,0,n-1,l,r);}
    array<ll, 2> querymn(ll id, ll l,ll r,ll i,ll j){
        push(id,l,r);
        if(l>j||r<i)return {INF, INF};
        if(l>=i&&r<=j)return mn[id];
        ll m=(l+r)/2;
        return min(querymn(id*2,l,m,i,j),querymn(id*2+1,m+1,r,i,j));
    }

    array<ll, 2> querymx(ll l, ll r){return querymx(1,0,n-1,l,r);}
    array<ll, 2> querymx(ll id, ll l,ll r,ll i,ll j){
        push(id,l,r);
        if(l>j||r<i)return {-INF, -INF};
        if(l>=i&&r<=j)return mx[id];
        ll m=(l+r)/2;
        return max(querymx(id*2,l,m,i,j),querymx(id*2+1,m+1,r,i,j));
    }

};

struct SegTree {
    
    vll st;
    ll n;

    SegTree () {}
    SegTree (ll n):n(n), st(4*n+4, INF) {}

    void update(ll i, ll v){update(1,0,n-1,i,v);}
    void update(ll id,ll l,ll r,ll i,ll v){
        if(l==r)st[id] = v;
        else{
            ll m = (l+r)/2;
            if(i<=m) update(id*2,l,m,i,v);
            else update(id*2+1,m+1,r,i,v);
            st[id] = min(st[id*2], st[id*2+1]);
        }
    }

	// encontrar minimo indice tal que x>=a este
	ll find (ll x) { return find (1, 0, n-1, x); }
	ll find (ll id, ll l, ll r, ll x) {
		if (st[id]>x) return INF;
		if (l == r) return l;
		ll m = (l+r)/2;
		if (st[id*2] <= x) return find(id*2, l, m, x);
		return find(id*2+1, m+1, r, x);
	}
	

};

ll solve (int n, vector<int> a, ll sig) {

	ll mx = *max_element(all(a));
	vector<vll> ps(n+1);
	fore (i, 1, n+1) ps[a[i]].pb(i);

	SegTree st(n+2);
	SegTreeLazy pf(n+2), g(n+2);
	pf.build(1, 0, n+1);
	g.build(1, 0, n+1);

	ll ans = 1;

	fore (i, 1, n+1) pf.update(i, n, +sig);
	fo (i, n+2) st.update(i, INF);

	for (ll x = 1; x <= mx; x++) {
		if (ps[x].size() == 0) continue;

		for (ll i: ps[x]) {
			pf.update(i, n, -sig);
			g.update(i, n, +1);
		}


		vector<array<ll, 2>> rd;
		
		// fo (_, ps[x].size()-1) {
		// 	rd.pb(pf.querymn(ps[x][_], ps[x][_+1]-1));
		// 	rd.pb(pf.querymx(ps[x][_], ps[x][_+1]-1));
		// }

		// rd.pb(pf.querymn(ps[x].back(), n));
		// rd.pb(pf.querymx(ps[x].back(), n));
		// rd.pb(pf.querymn(0, ps[x][0]-1));
		// rd.pb(pf.querymx(0, ps[x][0]-1));

		fo (i, n+1) rd.pb(pf.querymn(i, i));

		sort(all(rd));
		rd.erase(unique(all(rd)), rd.end());

		for (auto [_, i]: rd) {
			ll g_i = g.querymn(i, i)[0], pf_i = pf.querymn(i, i)[0];
			auto p = st.find(g_i-pf_i);
			if (p<i) {
				ans = max(ans, g_i-g.querymn(p, p)[0]);
			}
			st.update(i, g_i-pf_i);
		}
		for (auto [_, i]: rd) {
			st.update(i, INF);

		}
		for (ll i: ps[x]) {
			pf.update(i, n, -sig);
			g.update(i, n, -1);
		}
	}
	return ans;
}

int sequence(int n, vector<int> a) {

	{auto b = a;
	a.clear();
	a.pb(0);
	for (ll x: b) a.pb(x);
	a.pb(0);}
	
	ll ans = solve(n, a, +1);
	ans = max(ans, solve(n, a, -1));

	return ans;
}

컴파일 시 표준 에러 (stderr) 메시지

sequence.cpp:42:22: warning: overflow in conversion from 'double' to 'int' changes value from '1.0e+18' to '2147483647' [-Woverflow]
   42 | const int INF = 1e18 + 7;
      |                 ~~~~~^~~
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…
#결과 실행 시간메모리채점기 출력
결과를 불러오는 중입니다…