import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static final int LEN = 150000;
static final int SQ = 400;
static int N, L, M, bLen;
static int[] pos = new int[LEN];
static int[] a = new int[LEN];
static int[] b = new int[LEN];
static int[] next = new int[SQ * 2];
static Bucket[] buckets = new Bucket[SQ];
static class Bucket {
int size;
int[] A = new int[SQ * 2];
int[] cameras = new int[SQ * 2];
int[] cover = new int[SQ * 2];
int end() {
return size > 0 ? pos[A[size - 1]] : 0;
}
int bound(int x) {
int left = 0, right = size - 1, mid;
int k = size;
while (left <= right) {
mid = (left + right) / 2;
if (pos[A[mid]] > x) {
k = Math.min(k, mid);
right = mid - 1;
} else {
left = mid + 1;
}
}
return k;
}
void update() {
for (int l = 0, r = 0; l < size; ++l) {
while (r < size && pos[A[r]] <= pos[A[l]] + L) ++r;
next[l] = r;
}
for (int r = size - 1; r >= 0; --r) {
cameras[r] = next[r] == size ? 1 : cameras[next[r]] + 1;
cover[r] = next[r] == size ? pos[A[r]] + L : cover[next[r]];
}
}
void pop(int elem) {
int k = -1;
for (int i = 0; i < size; ++i) {
if (A[i] == elem) {
k = i;
break;
}
}
size--;
for (int i = k; i < size; ++i) A[i] = A[i + 1];
update();
}
void push(int elem) {
int left = 0, right = size - 1, mid;
int k = size;
while (left <= right) {
mid = (left + right) / 2;
if (pos[A[mid]] > pos[elem]) {
k = Math.min(k, mid);
right = mid - 1;
} else {
left = mid + 1;
}
}
size++;
for (int i = size - 1; i > k; --i) A[i] = A[i - 1];
A[k] = elem;
update();
}
void pushBack(int index) {
A[size++] = index;
}
}
static void init() {
for (int i = 0; i < bLen; ++i) buckets[i].size = 0;
for (int i = 0; i < N; ++i) buckets[i / SQ].pushBack(a[i]);
for (int i = 0; i < bLen; ++i) buckets[i].update();
}
static void normalize() {
for (int i = 0, k = 0; i < bLen; ++i) {
for (int j = 0; j < buckets[i].size; ++j, ++k) {
a[k] = buckets[i].A[j];
b[a[k]] = k / SQ;
}
}
init();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
L = sc.nextInt();
M = sc.nextInt();
bLen = N / SQ + 1;
for (int i = 0; i < N; ++i) {
pos[i] = sc.nextInt();
a[i] = i;
b[i] = i / SQ;
}
for (int i = 0; i < bLen; i++) {
buckets[i] = new Bucket();
}
init();
for (int q = 0, j = 0; q < M; ++q, ++j) {
if (j == SQ - 1) {
j = 0;
normalize();
}
int index = sc.nextInt();
int newY = sc.nextInt();
buckets[b[index]].pop(index);
pos[index] = newY;
b[index] = bLen - 1;
for (int k = 0; k < bLen; ++k) {
if (newY <= buckets[k].end()) {
b[index] = k;
break;
}
}
buckets[b[index]].push(index);
int cameraCount = buckets[0].cameras[0];
int lastCovered = buckets[0].cover[0];
for (int k = 1; k < bLen; ++k) {
if (buckets[k].size == 0 || buckets[k].end() <= lastCovered) continue;
int boundIndex = buckets[k].bound(lastCovered);
cameraCount += buckets[k].cameras[boundIndex];
lastCovered = buckets[k].cover[boundIndex];
}
System.out.println(cameraCount);
}
sc.close();
}
}
LEN
과 SQ
는 전체 길이와 버킷 수를 정의해 코끼리의 위치 및 버킷 구조의 크기를 설정한다.buckets
는 각 버킷에 담긴 코끼리의 상태를 저장하며, size
, A
, cameras
, cover
배열로 이루어져 있다.init
메서드버킷 초기화와 코끼리 초기 위치 설정을 수행한다. 이후 각 버킷마다 필요한 카메라 개수를 계산해 초기 상태를 완성한다.
normalize
메서드코끼리의 위치가 정렬되도록 버킷 내 순서를 재조정하고, init
메서드로 초기화를 다시 수행한다.
update
및 push
, pop
메서드updat
e는 각 버킷 내 카메라와 커버 범위를 새롭게 설정해 위치 변경에 따른 카메라 개수 변화를 반영한다.
push
는 특정 위치에 코끼리를 추가하며 위치를 갱신한다.
pop
은 특정 위치의 코끼리를 제거해 이동 시에도 빠르게 업데이트되도록 돕는다.
어렵지뭐...어려운거지뭐...하지만 코끼리 위치가 자주 변경되므로 위치를 관리하는 데 효율적인 데이터 구조를 선택하는 것이 핵심이었다. 각 버킷마다 필요한 카메라 개수를 계산해 카메라를 최소화하며, 카메라 범위 내에 코끼리가 모두 포함되도록 한 점이 중요한 포인트였다.