#include #include typedef struct { int key, id; } data; typedef struct { data *obj; int size, max_size; } min_max_heap; int get_min(min_max_heap* h) { return h->obj[0].key; } int get_argmin(min_max_heap* h) { return h->obj[0].id; } int get_max(min_max_heap* h) { if (h->size == 1) return h->obj[0].key; else return h->obj[1].key; } int get_argmax(min_max_heap* h) { if (h->size == 1) return h->obj[0].id; else return h->obj[1].id; } void push(min_max_heap* h, data x) { int i = (h->size)++; data tmp; if ((i & 1) != 0 && x.key < h->obj[i^1].key) { h->obj[i] = h->obj[i^1]; h->obj[i^1] = x; i ^= 1; } else h->obj[i] = x; int j, k = ((i >> 1) + 1) >> 1; if (k == 0) return; j = (k - 1) << 1; if (h->obj[i].key < h->obj[j].key) { while (k > 0) { if (h->obj[i].key < h->obj[j].key) { tmp = h->obj[j]; h->obj[j] = h->obj[i]; h->obj[i] = tmp; k >>= 1; i = j; j = (k - 1) << 1; } else break; } } else if (h->obj[i].key > h->obj[j^1].key) { j ^= 1; while (k > 0) { if (h->obj[i].key > h->obj[j].key) { tmp = h->obj[j]; h->obj[j] = h->obj[i]; h->obj[i] = tmp; k >>= 1; i = j; j = ((k - 1) << 1) ^ 1; } else break; } } } data pop_min(min_max_heap* h) { int i = 0, j = 2, k = 2; data output = h->obj[0], tmp; h->obj[0] = h->obj[--(h->size)]; while (j < h->size) { if (j + 2 < h->size && h->obj[j+2].key < h->obj[j].key) { j += 2; k++; } if (h->obj[i].key > h->obj[j].key) { tmp = h->obj[j]; h->obj[j] = h->obj[i]; h->obj[i] = tmp; k <<= 1; i = j; j = (k - 1) << 1; } else break; } if (j < h->size) return output; if (i < h->size - 1 && h->obj[i].key > h->obj[i^1].key) { tmp = h->obj[i^1]; h->obj[i^1] = h->obj[i]; h->obj[i] = tmp; i ^= 1; } k = ((i >> 1) + 1) >> 1; j = ((k - 1) << 1) ^ 1; while (k > 0) { if (h->obj[i].key > h->obj[j].key) { tmp = h->obj[j]; h->obj[j] = h->obj[i]; h->obj[i] = tmp; k >>= 1; i = j; j = ((k - 1) << 1) ^ 1; } else break; } return output; } data pop_max(min_max_heap* h) { if (h->size == 1) return h->obj[--(h->size)]; int i = 1, j = 2, k = 2; data output = h->obj[1], tmp; h->obj[1] = h->obj[--(h->size)]; while (j < h->size) { if (j + 1 < h->size) { j++; if (j + 2 < h->size && h->obj[j+2].key > h->obj[j].key) { j += 2; k++; } else if (j + 1 < h->size && h->obj[j+1].key > h->obj[j].key) { j++; k++; } } if (h->obj[i].key < h->obj[j].key) { tmp = h->obj[j]; h->obj[j] = h->obj[i]; h->obj[i] = tmp; k <<= 1; i = j; j = (k - 1) << 1; } else break; } if (j < h->size) return output; i = (i >> 1) << 1; if (i < h->size - 1 && h->obj[i].key > h->obj[i^1].key) { tmp = h->obj[i^1]; h->obj[i^1] = h->obj[i]; h->obj[i] = tmp; } k = ((i >> 1) + 1) >> 1; j = (k - 1) << 1; while (k > 0) { if (h->obj[i].key < h->obj[j].key) { tmp = h->obj[j]; h->obj[j] = h->obj[i]; h->obj[i] = tmp; k >>= 1; i = j; j = (k - 1) << 1; } else break; } return output; } const int sup = 1 << 20; typedef struct { int left, right, flag, sum, len; } seg_node; void init_node(seg_node v[], int leaf[], int k, int l, int r) { v[k].left = l; v[k].right = r; v[k].flag = 1; v[k].sum = 0; if (l < r) { v[k].len = sup; init_node(v, leaf, k << 1, l, (l + r) / 2); init_node(v, leaf, (k << 1) ^ 1, (l + r) / 2 + 1, r); } else { v[k].len = 1; leaf[l] = k; } } void update_flag(seg_node v[], int leaf[], int k, int x) { int i, j = leaf[k]; v[j].flag = x; for (i = j >> 1; i > 0; j = i, i >>= 1) v[i].flag = (v[j].flag > v[j^1].flag)? v[j].flag: v[j^1].flag; } void update_sum(seg_node v[], int leaf[], int k, int x) { int i, j = leaf[k]; v[j].sum += x; for (i = j >> 1; i > 0; j = i, i >>= 1) v[i].sum = ((v[j].sum <= v[j].len)? v[j].sum: v[j].len) + ((v[j^1].sum <= v[j^1].len)? v[j^1].sum: v[j^1].len); } int get_flag(seg_node v[], int leaf[], int k) { return v[leaf[k]].flag; } int get_sum(seg_node v[], int k, int l, int r) { if (v[k].right < l || v[k].left > r) return 0; else if (v[k].left >= l && v[k].right <= r) return v[k].sum; else return get_sum(v, k << 1, l, r) + get_sum(v, (k << 1) ^ 1, l, r); } int BS_left(seg_node v[], int k, int l, int r) { int tmp; if (v[k].flag == 0 || v[k].right < l || v[k].left > r) return r + 1; else if (v[k].left == v[k].right) return v[k].left; else { tmp = BS_left(v, k << 1, l, r); if (tmp <= r) return tmp; else return BS_left(v, (k << 1) ^ 1, l, r); } } int BS_right(seg_node v[], int k, int l, int r) { int tmp; if (v[k].flag == 0 || v[k].right < l || v[k].left > r) return l - 1; else if (v[k].left == v[k].right) return v[k].left; else { tmp = BS_right(v, (k << 1) ^ 1, l, r); if (tmp >= l) return tmp; else return BS_right(v, k << 1, l, r); } } void chmin(int* a, int b) { if (*a > b) *a = b; } int main() { int i, N, A[100001], B[100001], Z[100001]; scanf("%d", &N); for (i = 1; i <= N; i++) scanf("%d", &(A[i])); for (i = 1; i <= N; i++) scanf("%d", &(B[i])); for (i = 1; i <= N; i++) scanf("%d", &(Z[i])); int A_inv[100001], B_inv[100001], Z_inv[100001]; for (i = 1; i <= N; i++) { A_inv[A[i]] = i; B_inv[B[i]] = i; Z_inv[Z[i]] = i; } char meet[2][100001] = {}; data d; min_max_heap h[2][2][100001]; int j, k, leaf[3][100001]; seg_node v[3][262144]; for (i = 0; i < 3; i++) init_node(v[i], leaf[i], 1, 1, N); for (i = 1; i <= N; i++) { for (j = 0; j < 2; j++) { for (k = 0; k < 2; k++) { h[j][k][i].obj = (data*)malloc(sizeof(data) * 2); h[j][k][i].size = 0; h[j][k][i].max_size = 2; } } } for (i = 1; i <= N; i++) { if (Z[A[i]] == B[i]) { meet[0][i] = 1; meet[1][i] = 1; update_sum(v[2], leaf[2], i, 1); } else if (B_inv[Z[A[i]]] > i) { d.key = B_inv[Z[A[i]]]; d.id = i; push(&(h[0][1][i]), d); d.key = i; d.id = B_inv[Z[A[i]]]; push(&(h[1][0][B_inv[Z[A[i]]]]), d); } else { d.key = B_inv[Z[A[i]]]; d.id = i; push(&(h[0][0][i]), d); d.key = i; d.id = B_inv[Z[A[i]]]; push(&(h[1][1][B_inv[Z[A[i]]]]), d); } } printf("%d\n", get_sum(v[2], 1, 1, N)); int l, tmp; for (k = 2; k < N; k++) { i = A_inv[k]; if (i < N && A[i+1] < k) { update_flag(v[0], leaf[0], i + 1, 0); if (get_flag(v[1], leaf[1], i + 1) == 0) { update_flag(v[2], leaf[2], i + 1, 0); v[2][leaf[2][i]].len += v[2][leaf[2][i+1]].len; v[2][leaf[2][i+1]].len = 0; update_sum(v[2], leaf[2], i, v[2][leaf[2][i+1]].sum); update_sum(v[2], leaf[2], i + 1, -v[2][leaf[2][i+1]].sum); } for (j = 0; j < 2; j++) { if (h[0][j][i].size >= h[0][j][i+1].size) { while (h[0][j][i+1].size > 0) { d = pop_min(&(h[0][j][i+1])); push(&(h[0][j][i]), d); if (h[0][j][i].size == h[0][j][i].max_size) { h[0][j][i].max_size *= 2; h[0][j][i].obj = (data*)realloc(h[0][j][i].obj, sizeof(data) * h[0][j][i].max_size); } } free(h[0][j][i+1].obj); } else { while (h[0][j][i].size > 0) { d = pop_min(&(h[0][j][i])); push(&(h[0][j][i+1]), d); if (h[0][j][i+1].size == h[0][j][i+1].max_size) { h[0][j][i+1].max_size *= 2; h[0][j][i+1].obj = (data*)realloc(h[0][j][i+1].obj, sizeof(data) * h[0][j][i+1].max_size); } } free(h[0][j][i].obj); h[0][j][i] = h[0][j][i+1]; } } tmp = BS_right(v[1], 1, 1, i); while (h[0][0][i].size > 0 && (get_max(&(h[0][0][i])) >= tmp || meet[0][get_argmax(&(h[0][0][i]))] != 0)) { d = pop_max(&(h[0][0][i])); if (meet[0][d.id] != 0) continue; meet[0][d.id] = 1; meet[1][d.key] = 1; update_sum(v[2], leaf[2], i, 1); } tmp = BS_left(v[1], 1, BS_left(v[0], 1, i + 1, N), N) - 1; while (h[0][1][i].size > 0 && (get_min(&(h[0][1][i])) <= tmp || meet[0][get_argmin(&(h[0][1][i]))] != 0)) { d = pop_min(&(h[0][1][i])); if (meet[0][d.id] != 0) continue; meet[0][d.id] = 1; meet[1][d.key] = 1; update_sum(v[2], leaf[2], BS_right(v[1], 1, 1, d.key), 1); } } if (i > 1 && A[i-1] < k) { update_flag(v[0], leaf[0], i, 0); if (get_flag(v[1], leaf[1], i) == 0) { update_flag(v[2], leaf[2], i, 0); l = BS_right(v[2], 1, 1, i); v[2][leaf[2][l]].len += v[2][leaf[2][i]].len; v[2][leaf[2][i]].len = 0; update_sum(v[2], leaf[2], l, v[2][leaf[2][i]].sum); update_sum(v[2], leaf[2], i, -v[2][leaf[2][i]].sum); } l = BS_right(v[0], 1, 1, i); for (j = 0; j < 2; j++) { if (h[0][j][l].size >= h[0][j][i].size) { while (h[0][j][i].size > 0) { d = pop_min(&(h[0][j][i])); push(&(h[0][j][l]), d); if (h[0][j][l].size == h[0][j][l].max_size) { h[0][j][l].max_size *= 2; h[0][j][l].obj = (data*)realloc(h[0][j][l].obj, sizeof(data) * h[0][j][l].max_size); } } free(h[0][j][i].obj); } else { while (h[0][j][l].size > 0) { d = pop_min(&(h[0][j][l])); push(&(h[0][j][i]), d); if (h[0][j][i].size == h[0][j][i].max_size) { h[0][j][i].max_size *= 2; h[0][j][i].obj = (data*)realloc(h[0][j][i].obj, sizeof(data) * h[0][j][i].max_size); } } free(h[0][j][l].obj); h[0][j][l] = h[0][j][i]; } } tmp = BS_right(v[1], 1, 1, l); while (h[0][0][l].size > 0 && (get_max(&(h[0][0][l])) >= tmp || meet[0][get_argmax(&(h[0][0][l]))] != 0)) { d = pop_max(&(h[0][0][l])); if (meet[0][d.id] != 0) continue; meet[0][d.id] = 1; meet[1][d.key] = 1; if (d.key < l) update_sum(v[2], leaf[2], l, 1); else update_sum(v[2], leaf[2], BS_right(v[2], 1, 1, d.key), 1); } tmp = BS_left(v[1], 1, BS_left(v[0], 1, l + 1, N), N) - 1; while (h[0][1][l].size > 0 && (get_min(&(h[0][1][l])) <= tmp || meet[0][get_argmin(&(h[0][1][l]))] != 0)) { d = pop_min(&(h[0][1][l])); if (meet[0][d.id] != 0) continue; meet[0][d.id] = 1; meet[1][d.key] = 1; update_sum(v[2], leaf[2], BS_right(v[1], 1, 1, d.key), 1); } } i = B_inv[k]; if (i < N && B[i+1] < k) { update_flag(v[1], leaf[1], i + 1, 0); if (get_flag(v[0], leaf[0], i + 1) == 0) { update_flag(v[2], leaf[2], i + 1, 0); v[2][leaf[2][i]].len += v[2][leaf[2][i+1]].len; v[2][leaf[2][i+1]].len = 0; update_sum(v[2], leaf[2], i, v[2][leaf[2][i+1]].sum); update_sum(v[2], leaf[2], i + 1, -v[2][leaf[2][i+1]].sum); } for (j = 0; j < 2; j++) { if (h[1][j][i].size >= h[1][j][i+1].size) { while (h[1][j][i+1].size > 0) { d = pop_min(&(h[1][j][i+1])); push(&(h[1][j][i]), d); if (h[1][j][i].size == h[1][j][i].max_size) { h[1][j][i].max_size *= 2; h[1][j][i].obj = (data*)realloc(h[1][j][i].obj, sizeof(data) * h[1][j][i].max_size); } } free(h[1][j][i+1].obj); } else { while (h[1][j][i].size > 0) { d = pop_min(&(h[1][j][i])); push(&(h[1][j][i+1]), d); if (h[1][j][i+1].size == h[1][j][i+1].max_size) { h[1][j][i+1].max_size *= 2; h[1][j][i+1].obj = (data*)realloc(h[1][j][i+1].obj, sizeof(data) * h[1][j][i+1].max_size); } } free(h[1][j][i].obj); h[1][j][i] = h[1][j][i+1]; } } tmp = BS_right(v[0], 1, 1, i); while (h[1][0][i].size > 0 && (get_max(&(h[1][0][i])) >= tmp || meet[1][get_argmax(&(h[1][0][i]))] != 0)) { d = pop_max(&(h[1][0][i])); if (meet[1][d.id] != 0) continue; meet[1][d.id] = 1; meet[0][d.key] = 1; update_sum(v[2], leaf[2], i, 1); } tmp = BS_left(v[0], 1, BS_left(v[1], 1, i + 1, N), N) - 1; while (h[1][1][i].size > 0 && (get_min(&(h[1][1][i])) <= tmp || meet[1][get_argmin(&(h[1][1][i]))] != 0)) { d = pop_min(&(h[1][1][i])); if (meet[1][d.id] != 0) continue; meet[1][d.id] = 1; meet[0][d.key] = 1; update_sum(v[2], leaf[2], BS_right(v[0], 1, 1, d.key), 1); } } if (i > 1 && B[i-1] < k) { update_flag(v[1], leaf[1], i, 0); if (get_flag(v[0], leaf[0], i) == 0) { update_flag(v[2], leaf[2], i, 0); l = BS_right(v[2], 1, 1, i); v[2][leaf[2][l]].len += v[2][leaf[2][i]].len; v[2][leaf[2][i]].len = 0; update_sum(v[2], leaf[2], l, v[2][leaf[2][i]].sum); update_sum(v[2], leaf[2], i, -v[2][leaf[2][i]].sum); } l = BS_right(v[1], 1, 1, i); for (j = 0; j < 2; j++) { if (h[1][j][l].size >= h[1][j][i].size) { while (h[1][j][i].size > 0) { d = pop_min(&(h[1][j][i])); push(&(h[1][j][l]), d); if (h[1][j][l].size == h[1][j][l].max_size) { h[1][j][l].max_size *= 2; h[1][j][l].obj = (data*)realloc(h[1][j][l].obj, sizeof(data) * h[1][j][l].max_size); } } free(h[1][j][i].obj); } else { while (h[1][j][l].size > 0) { d = pop_min(&(h[1][j][l])); push(&(h[1][j][i]), d); if (h[1][j][i].size == h[1][j][i].max_size) { h[1][j][i].max_size *= 2; h[1][j][i].obj = (data*)realloc(h[1][j][i].obj, sizeof(data) * h[1][j][i].max_size); } } free(h[1][j][l].obj); h[1][j][l] = h[1][j][i]; } } tmp = BS_right(v[0], 1, 1, l); while (h[1][0][l].size > 0 && (get_max(&(h[1][0][l])) >= tmp || meet[1][get_argmax(&(h[1][0][l]))] != 0)) { d = pop_max(&(h[1][0][l])); if (meet[1][d.id] != 0) continue; meet[1][d.id] = 1; meet[0][d.key] = 1; if (d.key < l) update_sum(v[2], leaf[2], l, 1); else update_sum(v[2], leaf[2], BS_right(v[2], 1, 1, d.key), 1); } tmp = BS_left(v[0], 1, BS_left(v[1], 1, l + 1, N), N) - 1; while (h[1][1][l].size > 0 && (get_min(&(h[1][1][l])) <= tmp || meet[1][get_argmin(&(h[1][1][l]))] != 0)) { d = pop_min(&(h[1][1][l])); if (meet[1][d.id] != 0) continue; meet[1][d.id] = 1; meet[0][d.key] = 1; update_sum(v[2], leaf[2], BS_right(v[0], 1, 1, d.key), 1); } } printf("%d\n", get_sum(v[2], 1, 1, N)); } printf("%d\n", N); fflush(stdout); return 0; }