$O(t(n+m \lg (n+m)))$
처음에 아래부터 n, n-1, ..., 2, 1 과 같이 쌓여 있을 것이다. 이후 들어올 쿼리 qi를 누적해서 써보면,
ai: n, n-1, ..., 2, 1, q0, q1, q2 ...
위 수열에서 x 이전의 항중 값이 x인 항의 가장 큰 번호를 f(x) 라 하자.
구하고자 하는 답은 i번째 항과 f(ai)번째 항 사이에 있는 수의 종류와 같음을 알 수 있다.
쿼리 x가 들어올 때마다 f(x)를 이용하여 bit를 업데이트 하는 방식으로 해결할 수 있다.
#include<cstdio> const int MXN = 1e5; int t, n, m, a[MXN + 1], bit[MXN * 2 + 1]; void update(int h) { for (; h <= n + m; h += h&-h) bit[h]++; } int query(int h) { int s = 0; for (; h; h -= h&-h) s += bit[h]; return s; } int main() { for (scanf("%d", &t); t--;) { scanf("%d %d", &n, &m); for (int i = 1; i <= n + m; i++) bit[i] = 0; int i = 1, x; for (; i <= n; i++) a[i] = n + 1 - i; for (; i <= n + m; i++) { scanf("%d", &x); printf("%d ", i - a[x] - 1 - query(i) + query(a[x])); update(a[x]); a[x] = i; } puts(""); } return 0; }
댓글 없음 :
댓글 쓰기