題目大意:
兩個長度爲的序列,m個操作,操作種類有兩種
①修改某個序列中的某個數
②查詢兩個序列中的某兩個區間合併後的中位數。
保證合併後的區間長度爲奇數。
保證任意時刻都滿足非嚴格單調遞增。
分析:
修改就直接改,
對於查詢而言,
我們顯然就是要求兩個區間合併後的第小,
那麼因爲序列都滿足非嚴格單調遞增,
那麼我們每次就找兩個區間的大比較,
那麼顯然
合併後的區間的前k個必定包含到
這時候我們再去找中的前小即可
最後或者某一個區間的左界已經越了的時候就找到答案了
注意可能區間長度沒有的情況即可
代碼:
#pragma GCC optimize(3)
#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <cstring>
#include <algorithm>
#define rep(i, st, ed) for (int i = st; i <= ed; i++)
#define rwp(i, ed, st) for (int i = ed; i >= st; i--)
#define N 500005
using namespace std;
int a[N], b[N], n, m, ans, rank;
int A, B, C, D;
void read(int &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s >= '0' && s <= '9') { x = x * 10 + (s - '0'); s = getchar(); }
x = x * f;
}
void dfs(int num) {
if (num == 1) {
if (C > D) printf("%d\n", a[A]);
else if (A > B) printf("%d\n", b[C]);
else printf("%d\n", min(a[A], b[C]));
return;
}
int AA = A + num / 2 - 1;
int CC = C + num / 2 - 1;
if (AA > B) AA = n + 1;
if (CC > D) CC = n + 1;
if (a[AA] < b[CC]) A = A + num / 2; else C = C + num / 2;
dfs(num - num / 2);
}
int main() {
freopen("median.in", "r", stdin);
freopen("median.out", "w", stdout);
scanf("%d %d", &n, &m);
rep(i, 1, n) read(a[i]); a[n + 1] = 0x7fffffff;
rep(i, 1, n) read(b[i]); b[n + 1] = 0x7fffffff;
int opt, x, y, z;
while (m--) {
read(opt);
if (opt == 1) {
read(z); read(x); read(y);
if (z == 0) a[x] = y; else b[x] = y;
} else {
read(A); read(B); read(C); read(D);
rank = ((B - A + 1) + (D - C + 1) + 1) / 2;
if (a[B] <= b[C]) {
if (rank <= B - A + 1) printf("%d\n", a[A + rank - 1]);
else printf("%d\n", b[C + (rank - (B - A + 1)) - 1]);
} else if (b[D] <= a[A]) {
if (rank <= D - C + 1) printf("%d\n", b[C + rank - 1]);
else printf("%d\n", a[A + (rank - (D - C + 1)) - 1]);
} else dfs(rank);
}
}
return 0;
}