Jzoj P6308 中間值___分治

題目大意:

兩個長度爲nn的序列a,ba,b,m個操作,操作種類有兩種
①修改某個序列中的某個數
②查詢兩個序列中的某兩個區間合併後的中位數。
保證合併後的區間長度爲奇數。
保證任意時刻a,ba,b都滿足非嚴格單調遞增。
在這裏插入圖片描述

分析:

修改就直接改,
對於查詢而言,
我們顯然就是要求兩個區間合併後的第kk小,
那麼因爲序列都滿足非嚴格單調遞增,
那麼我們每次就找兩個區間的k/2k/2大比較,
a[l+k/21]<b[ll+k/21]a[l+k/2-1]<b[ll+k/2-1]那麼顯然
合併後的區間的前k個必定包含a[l]a[l]a[l+k/21]a[l+k/2-1]
這時候我們再去找a[l+k/2,r],b[ll,ll+k/21]a[l+k/2,r],b[ll,ll+k/2-1]中的前kk/2k-k/2小即可
最後k=1k=1或者某一個區間的左界已經越了的時候就找到答案了
注意可能區間長度沒有k/2k/2的情況即可

代碼:

#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;
} 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章