PS/Problems
[Java] 백준 3653 영화 수집 - Lazy Segment Tree
CalicoCat22
2022. 3. 20. 17:06
https://www.acmicpc.net/problem/3653
3653번: 영화 수집
각 테스트 케이스에 대해서 한 줄에 m개의 정수를 출력해야 한다. i번째 출력하는 수는 i번째로 영화를 볼 때 그 영화의 위에 있었던 DVD의 개수이다. 상근이는 매번 영화를 볼 때마다 본 영화 DVD
www.acmicpc.net
leaf 노드의 경우 좌측부터 i번 영화가 node[i] 번째에 놓여있도록 하였다.
하지만 탐색 회수를 최적화하기 위해
해당 노드를 root로 가지는 트리에 대하여 mintree, maxtree로 나누어서
mintree[node] >= v 라면 그 트리는 놓여있는 위치의 값을 더해선 안되므로 return
maxtree[node] < v 라면 그 트리의 모든 노드는 1을 더해주므로 minlazy, maxlazy 모두 ++
솔직히 한번에 맞을줄 상상도 못했다.
import java.util.*;
import java.io.*;
public class p4_3653 {
static FastScanner fs = new FastScanner();
static PrintWriter pw = new PrintWriter(System.out);
static int n, m;
static int[] mintree, maxtree, minlazy, maxlazy;
public static void main(String[] args) {
int t = fs.nextInt();
while (t-- > 0){
n = fs.nextInt();
m = fs.nextInt();
mintree = new int[n * 4];
maxtree = new int[n * 4];
minlazy = new int[n * 4];
maxlazy = new int[n * 4];
init(1, n, 1);
while (m-- > 0){
int num = fs.nextInt();
int index = find(1, n, 1, num);
pw.print((index - 1) + " ");
update(1, n, 1, index);
change(1, n, 1, num);
}
pw.println();
}
pw.close();
}
static void change(int lo, int hi, int node, int i){
lazy(lo, hi, node);
if (i < lo || hi < i) return;
if (lo == hi){
mintree[node] = 1;
maxtree[node] = 1;
return;
}
int mid = (lo + hi) / 2;
change(lo, mid, node * 2, i);
change(mid + 1, hi, node * 2 + 1, i);
mintree[node] = Math.min(mintree[node * 2], mintree[node * 2 + 1]);
maxtree[node] = Math.max(maxtree[node * 2], maxtree[node * 2 + 1]);
}
static void update(int lo, int hi, int node, int v){
lazy(lo, hi, node);
if (maxtree[node] < v){
minlazy[node]++;
maxlazy[node]++;
return;
}
if (mintree[node] >= v) return;
int mid = (lo + hi) / 2;
update(lo, mid, node * 2, v);
update(mid + 1, hi, node * 2 + 1, v);
}
static int find(int lo, int hi, int node, int i){
lazy(lo, hi, node);
if (i < lo || hi < i) return -1;
if (lo == hi) return mintree[node];
int mid = (lo + hi) / 2;
return Math.max(find(lo, mid, node * 2, i), find(mid + 1, hi, node * 2 + 1, i));
}
static void lazy(int lo, int hi, int node){
if (minlazy[node] != 0){
mintree[node] += minlazy[node];
if (lo != hi){
minlazy[node * 2] += minlazy[node];
minlazy[node * 2 + 1] += minlazy[node];
}
minlazy[node] = 0;
}
if (maxlazy[node] != 0){
maxtree[node] += maxlazy[node];
if (lo != hi){
maxlazy[node * 2] += maxlazy[node];
maxlazy[node * 2 + 1] += maxlazy[node];
}
maxlazy[node] = 0;
}
}
static void init(int lo, int hi, int node){
if (lo == hi){
mintree[node] = lo;
maxtree[node] = lo;
return;
}
int mid = (lo + hi) / 2;
init(lo, mid, node * 2);
init(mid + 1, hi, node * 2 + 1);
mintree[node] = Math.min(mintree[node * 2], mintree[node * 2 + 1]);
maxtree[node] = Math.max(maxtree[node * 2], maxtree[node * 2 + 1]);
}
// ----------input function----------
static void sort(int[] a) {
ArrayList<Integer> L = new ArrayList<>();
for (int i : a)
L.add(i);
Collections.sort(L);
for (int i = 0; i < a.length; i++)
a[i] = L.get(i);
}
static class FastScanner {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer("");
String next() {
while (!st.hasMoreTokens()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
double nextDouble() {
return Double.parseDouble(next());
}
int[] readArray(int n) {
int[] a = new int[n];
for (int i = 0; i < n; i++)
a[i] = nextInt();
return a;
}
long nextLong() {
return Long.parseLong(next());
}
}
}