이 문제는 정말 쇼이다. . . 나는했다. . . 기록 할 수있는 좋은 느낌 세그먼트 트리. . .
주제 효과 : 당신에게 문자열을 줄 수는 가장 긴이 긴 다음 조건을 충족하도록 요청 문자열 : K의 발생보다는 각 번호, 또는이 아이가 가진 노 쇼의 문자열, 또는 그 이상의하십시오.
우리는 내가 확실히 먼이 조건을 충족 왼쪽 찾을 수 있도록 노력하겠습니다 각 위치는 다음 최대하지 미야을 유지 존중?
그렇다면 우리는 먼이 조건을 충족 찾을 수 있습니까? ? ? 그래서 우리는 몇 가지 물건을 유지해야합니까?
우리는 [] t 배열을 유지하는, t [J] = m 내가 j 위치에서 왼쪽으로 비트를 나타내며, 조건 만족 수가 유지 세그먼트 트리 (하나를 0으로는 K와 동일하거나보다 크다).
각각의 위치 나, 우리는 현재에서의 현재 위치에 대표 점을 C-1 추가 0 구간의 길이가 필요
우리는 t [I]를 논의 할 때마다 상기 I 위치 때 우측 지점으로서 [I] =의 X, X 좌측 지점을 제외한 나머지의 수 난 [I, I]이 범위로서 위치 될 수 있도록 X는 다른 0 번 등장된다 번만 내에 등장 0 확실히 가능하다 표시되므로 제 더하기 C-1 (-1 위치 때문에 더욱 실용적인 좌측 지점 (X)로 설명 할 필요가있는 경우)
그렇다면 우리 수가 의한 i 번째 위치에 [I] 나 위치, a는 [I] 위치의 값과 동일하게 사용 된 간격이 가능하도록 위치에 [I], 그 결과, 현재 위치가 나타난 고려 하지만 지금은되지. 우리는 필요
하나 개의 위치로부터 -1의 전체 값, a는 [I]의 간격을 더 이상 사용할 수 없습니다 나타내는 것이다. 그리고, (K)의 현재 위치에서 우리의 전방에 [I] 앞에 위치의 K-1 [I]의 위치의 이전 위치를 사용할 수 없지만, 오른쪽은 추가 이후 새로운 A [i]를 이 섹션을 사용할 수없는 사용할 수있게 될 것입니다, 원래의 값을 나타내는, 일의 범위 내에 있어야는 사용할 수 없습니다 사용할 수 있습니다.
#INCLUDE <. 비트 / stdc ++ H> #DEFINE가 긴 긴 LL #DEFINE의 LSON의 RT << 1 #DEFINE의 rson의 RT << 1 | 1 사용 스페이스 성병; CONST의 INT의 맥스 1E5 + = 6 ; 구조체 노드 { INT의 L, R; INT , 탄소 나노 튜브를 게으름 피우다; } 트리 [맥스 << 2 ]; int로 A [맥스]을; INT 사전 [맥스]; int로 N, C, K; 벡터 < INT > G [맥스]; 보이드 push_down ( INT의 RT) { 경우 + = (트리 [RT] .laze) { 트리 [LSON] .CNT 트리 [RT] .laze; 트리 [rson] .CNT + = 트리 [RT] .laze; 트리 [LSON] .laze + = 트리 [RT] .laze; 트리 [rson] .laze + = 트리 [RT] .laze; 트리 [RT] .laze = 0 ; } } 공극 buildtree ( INT의 RT, INT의 L, INT의 R) { 트리 [RT] 펜닐 = L 단계; 트리 [RT] .R = R; 트리 [RT] .laze = 0 ; 트리 [RT] .CNT = 0 ; 경우 (L의 == 된 R) { 반환 ; } INT 중간 = (L + R) >> 1 ; buildtree (LSON, L, MID); buildtree (rson 중간 + 1 , R); } 공극 업데이트 ( INT RT, INT UL, INT 우르 INT w) { INT의 L = 트리 [RT] 펜닐; INT의 R = 트리 [RT] .R; 만약 UL (<= 1 && R <= UR) { 트리 [RT] .CNT + = w; 트리 [RT] .laze + = w; 반환 ; } push_down (RT); INT 중간 = (L + R) >> 1 ; 경우 (UR <= MID) { 업데이트 (LSON, UL, UR, w); } 다른 경우 (UL> 중간) { 갱신 (rson, UL, UR, w); } 다른 { 갱신 (LSON, UL, 중간, w); 업데이트 (rson, 중간 + 1 , UR, w); } 트리 [RT] .CNT = 최대 (트리 [LSON] .CNT, 트리 [rson] .CNT); } INT 쿼리 ( INT RT) { INT의 L = 트리 [RT] 펜닐; INT의 R = 트리 [RT] .R; 경우 (L의 == 된 R) { 복귀 L; } (RT) push_down; int로 중간 = (L + R) >> 1 ; 경우 (트리 [LSON] == .CNT c) { 리턴 질의 (LSON); } 다른 경우 (트리 [rson] == .CNT c) { 리턴 질의 (rson); } 다른 { 반환 - 1 ; } } INT 의 main () { 동안 (~는 scanf ( " % D % D % D " , N, C, K)) { 위해 ( int로 I = 1 ; 나는 =에 c <; 내가 ++ ) { G [I]하는 명확한 (); G [I] .push_back ( 0 ); } memset 함수 (프리, 0 , 는 sizeof (예정)); 위한 ( int로 I = 1 ; 나는 <= N; I ++는 ) { 는 scanf ( " %의 D를 " , & A [I]); . G [A [내가]와 push_back (I); } buildtree ( 1 , 1 , N); 경우 (K ==의 1 ) { 의 printf ( " % D \ 없음 " , N); 계속 ; } INT ANS = 0 ; 위한 ( int로 I = 1 ; i가 <= N; 내가 ++ ) { INT (X) = A [I]; INT p = ++ 미리 [A [I]; 업데이트 ( 1 , I, I, C- 1 ); 경우 (G [A [I] [P- 1 ] + 1 <= G [A [I] [P] - 1 ) 업데이트 ( 1 , G [A [I] [P- 1 ] + 1 , G [A [I] [P] - 1 - 1 ); 경우 (p> = K) 업데이트 ( 1 , G [A [I] [PK] + 1 , G [A [I] [PK +1 , 1 ); INT POS = 쿼리 ( 1 ); 경우 (POS =! - 1 ) { ANS = 최대 (ANS I-POS + 1 ); } } 의 printf ( " % D \ 없음 " , ANS); } 반환 0 ; }