질문의 의미 : 길이 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을 시도하지 않은) 시도 할 수 있습니다 관심이 있습니다.
다음과 같이 스택 코드는 다음과 같습니다
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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 코드이다 :
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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;
}
备注:本题堆的速度比<set>要快,但是代码实现难度更大,推荐用<set>.