AtCoderGC038B이 - 세그먼트 보고서 문제 해결을 정렬

질문의 의미 : 길이 N의 순열을 감안할 때, 당신이 큰 작은 만 K 연속 시퀀스, Q입니다 길이의 종류를 수행 할 수 있습니다 얼마나 많은 다른 배열 정렬 후 형성 될 수있다?

데이터 범위 : 1 <= N, K <= 20, K <= N.

----------------------------------- 분할 선 ------------- -------------------

이 질문의 분석, 우리가 발견 만 N-K + 1 정렬 상황 상한 N-K의 대답이있을 것을 의미합니다 원래 배열에만 N-K + 1 창에서 K 연속 시퀀스의 길이 + 1.

연속 시퀀스 반복 횟수 M, M 지역 사회의 정도를 고려 마이너스 대답이다.

그래서 나머지 문제는 각 번호 M. 정렬 후 동일한 연속 순서를 계산하는

간단한 방법 : 열거 길이 K를 내림차순으로 비트 열의 각 간격은, 동일한 통계 및 다른 배열이 배치되어 수 (CNT)를 비교 원래 구성을 구하는 각 CNT-1은 누적 될 수있다.

O의 시간 복잡도 (N ^ 2 *가 klog (K)).

최적화 방법을 고려하십시오.

A1, A2, A3, ........ 원래 구성을 제공한다.

원래의 P (L, R)에 배치되어 정렬이 후, 간격 [L, R]를 가정하자.

그런 경우, P (L1, R1) = P (L2, R2) 및 R1 - R2 = +1 L1 - L2 + 1 = K.

오직 다음 두 조건에 해당하는 경우, 다음이 보유하는 경우 :

(1) 구간 [L1 (R1)] 및 간격 [L2, R2] 이미 (소에서 대형) 주문.

(2) 간격 [L1 (R1)] 및 간격 [L2, R2에 인접한, 즉 L2 = L1 + 1, R2 = R1 + 1 및 분 [L1, R2]는 [L1], 맥스 [L1, R2가 = ]]이 [R2가 =. 

결론 (1) 정확성 분명히.

주요 토론 결론 (2) 정확성 :

우리는 [L2, R1]의 간격 [L1, R1] 및 간격 [L2, R2] 단면을 알고, 간격 [L1, R2]에 있습니다.

당신은 단지 간격 [L2, R1]을 고려할 경우, 결과는 분명 같은 종류입니다.

그리고 P (L1, R1) <=> P (L2, R1) U [L1, L2-1] 크기 관계 간격 [L2, R1] 대응하는 위치에 기초하여 상기 삽입 부의 모든 요소.

인터벌 [L2, R2] 공감.

그래서 우리는 구간 [L2, R1] 영향에 정렬 간격 [L1, L2-1] 및 구간 [R1 + 1, R2]을 해결할 필요가있다.

만약 [L1 (R1)] 및 [L2, R2] 비 인접 아닌 경우 (1), P (L1, R1)! = P (L2, R1), P (L2, R2)! P = (L2, R1), P (L1, R1)! P = (L2, R1)! P = (L2, R2)가 존재하지 않는다.

그런 경우 L2 L1 + 1 때 = 분 [L1, R2는] = 경우 [L1]은 P (L1, R1) = P (L2, R1)은 맥스 [L1, R2]는 [R2]을 =하면 는 P :. P (L1, R1) = P (L2, R1) = P (L2, R2)의 전달에서 본 (L2, R2) = P (L2, R1). 결론 설립했다.

QED.

그래서이 두 결론, 우리는 먼저 원래 배열 석권 반복 (1)의 수를 결정할 수 있고, 상승하는 부분의 수 K와 동일한 계산 된 길이보다 크다.

(2)에서, 우리는 첫 번째 구간 [1, K], 최대 및 최소 유지 보수를 선택하는 경우, 그 오른쪽의 좌우 지점 포인터 포인트는 각각 구간 [1 [2, K + 1] 구간에 진행 , K]와 [2, K + 1], 최소 [1, + 1 K]는 [1]과 최대 [1, K + 1]을 만족하는 경우 [K + 1]., 축적 = 여부를 판정한다 M에, 그렇지 않으면 지금까지 N에 대한 권리 지점까지 오른쪽으로 계속합니다.

최대 및 최소 유지 보수 간격은 STL 스택 설정하거나 유지 보수 동적 일 수 있습니다.

삽입 및 결실 복잡도 O (logN), 탐색 시간 복잡도 O (N)은, 전체 시간 복잡도 스루. O (NlogN)이다.

수동 유지 보수, 조금 지루하지만, 전체 시간 복잡도는 O (N)로 감소하는 경우, 우리는 (나는 QAQ을 시도하지 않은) 시도 할 수 있습니다 관심이 있습니다.

다음과 같이 스택 코드는 다음과 같습니다

#INCLUDE <. 비트 / stdc ++ H> #DEFINE가 긴 긴 것이다
 #DEFINE 다용도 make_pair의
 #DEFINE에 대해 렙 (나는 A는, b) (INT I = (A) 내가 = (b) "; 나는 ++)
 #DEFINE 당을 ( 난> = (B), 난 -)의 경우 나, a는 b)는 (i = (a int)를 사용하여 네임 스페이스 성병; 
쌍 타입 정의 < INT , INT > PII; 
타입 정의 를 두 번 DB;
CONST의 INT N = + 1E6 (50) ;
INT의 N, K, A [N], CNT = 0 , 플래그 = 0 ; 
INT ANS = 0 , 맥스 미네소타, PMAX, PMIN;
int로 [N] F를 힘 [N]을;



 
 
priority_queue < INT 벡터 < INT > 큰 < INT >> Q; 
priority_queue < INT 벡터 < INT > 이하 < INT >> P; 
인라인 INT의 판독 () {
     INT (X) = 0 , F = 1 ;
     CH = getchar가 ();
    동안 (CH2 < ' 0 ' || CH> ' 9 ' ) { 경우 (CH2 == ' - ' ) F = - 1 ; CH = getchar가 ();
    동안 (CH2> = ' 0 ' && CH <=에서 ' 9 ' ) {(X) = (X << 3 ) + (X << 1 ) + (CH는 ^ 48 ); CH = getchar가 ();}
     리턴 의 X *의 F; 
} 
공극 초기화 () { 
    N =) (판독; K = 판독 (); 
    렙 (I, 1 , n)은 [I]가 = 읽기 (); 
    렙 (I, 1 , K) p.push (a [I]) q.push (a [I]); 
    렙 (I, 2 , N) {
         경우 (a [I]>은 [I- 1 ]) {
             INT  합 =0 ;
            동안 (a [I]>은 [I- 1 ] && 난 <= N)의 난 합 ++ ++ ;
            경우 (합계> = K- 1 ) CNT ++ ; 
        } 
    } 
    ANS = N-K + 1 ;
    INT의 L = 1 , R = K;
    반면 (R <= N) { 
        R을 ++ ;
        경우 (R> n)의 분해 ;
        반면 (힘 [q.top ()]) q.pop (); 
        반면 (F [p.top ()]) p.pop ();
        경우 (a [1] == q.top () && A [R]> p.top ()) {
            q.pop (); p.push (a [R]);  
            q.push (a [R]);
            F [A [L]] = 1 ; 
            ANS - ; 
        } 
        다른  경우 (a [1] == q.top () && A [R] < p.top ()) { 
            q.pop (); p.push (a [R]); 
            q.push (a [R]); 
            F [A [L]] = 1 ; 
        } 
        다른  경우 (a [1] == p.top ()) { 
            p.pop (); p.push (a [R]); 
            q.push (a [R]); 
            힘 [A [L]] = 1 ; 
        } 
        다른  경우 (a [L]! = q.top () && A [L]! = p.top ()) { 
            p.push (a [R]); q.push (a [R]);
            F [A [1] = 1 , 힘 [A [L]] = 1 ; 
        } 
        리터 ++ ; 
    } 
    경우 (CNT 라!)의 printf ( " % D \ 없음 " , ANS);
    사람 의 printf ( " % D \ 없음 " , ANS - CNT + 1 ); 
} 
INT 의 main () { 
    초기화 (); 
    반환  0 ; 
}
코드보기

다음 <설정>는 STL 코드이다 :

#include<bits/stdc++.h>

#define ll long long
#define mp make_pair
#define rep(i, a, b) for(int i = (a);i <= (b);i++)
#define per(i, a, b) for(int i = (a);i >= (b);i--)

using namespace std;

typedef pair<int, int> pii;
typedef double db;
const int N = 1e6 + 50;
int n, k, a[N], ans = 0,  cnt;
set <int> s;
set <int>::iterator it;
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
    while(ch >='0' && ch <='9'){x = (x<<3)+(x<<1)+(ch^48); ch = getchar();}
    return x*f;
}
void init(){
    n = read(); k = read();
    rep(i, 1, n) a[i] = read();
    rep(i, 1, k) s.insert(a[i]);
    rep(i, 2, n){
        if(a[i] > a[i-1]){
            int sum = 0;
            while(a[i] > a[i-1] && i <= n) i++, sum++;
            if(sum >= k-1) cnt ++;
        }
    }
    ans = n-k+1;
    int l = 1, r = k;
    while(l <= r && r <= n){
        r++;
        if(r > n) break;
        s.insert(a[r]);
        if(*(s.rbegin()) == a[r] && (*s.begin()) == a[l]) ans --;
        s.erase(a[l]); 
        l++;
    }
    if(!cnt) printf("%d\n", ans);
    else printf("%d\n", ans - cnt+1);
}
int main(){
    init();
    return 0;
}
View Code

 备注:本题堆的速度比<set>要快,但是代码实现难度更大,推荐用<set>.

추천

출처www.cnblogs.com/smilke/p/11567189.html