2020 wannaflyキャンプ1日目IK小数点クエリ - ブロック

トピックリンク:ポイント私はああ╭(╯^╰)╮

効果の件名:

    複数のオペレーティング・
    テイクの範囲 m i n 私に
    求めるのセクション k K 小さな

問題解決のアイデア:

    ブロックの処理、ブロックサイズが設定されています p P
    ブロック、更新クエリソート
    直接ピースに二分答えを u p p e r _ b o u n d 上界
    点散乱暴力チェックのいずれかの側の
    更新時間複雑: p × l o g p + n p P×のlogP + \ FRAC {N} {P}
    クエリ時間の複雑さ: l o g n × ( n p × l o g p + p ) LOGN×(\ FRAC {N} {P}×のlogP + P)

コア:算術シーケンスを処理ツリー差

#include<bits/stdc++.h>
#define rint register int
#define deb(x) cerr<<#x<<" = "<<(x)<<'\n';
using namespace std;
typedef long long ll;
using pii = pair <int,int>;
const int maxn = 8e4 + 5;
int n, m, a[maxn];
int size, bnum, lz[maxn];
int L[maxn], R[maxn];
vector <int> v[maxn];

inline int get_id(int x){
	return x / size;
}

inline void update(int l, int r, int x){
	int id = get_id(l);
	if(L[id] < l){
		v[id].clear();
		for(int i=L[id]; i<=R[id]; i++){
			a[i] = min(a[i], lz[id]);
			if(i >= l && i <= r) a[i] = min(a[i], x);
			v[id].push_back(a[i]);
		}
		sort(v[id].begin(), v[id].end());
		id++;
	} 
	if(id >= bnum) return;
	while(R[id]<=r && id<bnum){
		lz[id] = min(lz[id], x);
		id++;
	} 
	
	if(L[id]>r || id>=bnum) return;
	v[id].clear();
	for(int i=L[id]; i<=R[id]; i++){
		a[i] = min(a[i], lz[id]);
		if(i >= l && i <= r) a[i] = min(a[i], x);
		v[id].push_back(a[i]);
	}
	sort(v[id].begin(), v[id].end());
}

inline int ck(int l, int r, int k){
	int id = get_id(l), res = 0;
	if(L[id] < l){
		for(int i=l; i<=min(R[id], r); i++){
			a[i] = min(a[i], lz[id]);
			if(a[i] <= k) res++;
		}
		id++;
	}
	if(id >= bnum) return res;
	while(R[id]<=r && id<bnum){
		if(lz[id] <= k) res += R[id] - L[id] + 1;
		else res += upper_bound(v[id].begin(), v[id].end(), k) - v[id].begin();
		id++;
	}
	if(L[id]>r || id>=bnum) return res;
	for(int i=L[id]; i<=min(R[id], r); i++){
		a[i] = min(a[i], lz[id]);
		if(a[i] <= k) res++;
	}
	return res;
}

inline int query(int L, int R, int k){
	int l = 1, r = 1e9, mid;
	while(l <= r){
		mid = l + r >> 1;
		if(ck(L, R, mid) >= k) r = mid - 1;
		else l = mid + 1;
	}
	return l;
}

int main() {
	scanf("%d%d", &n, &m);
	for(int i=0; i<n; i++) scanf("%d", a+i);
	size = sqrt(n), bnum = (n - 1) / size + 1;
	for(int i=0; i<bnum; i++){
		lz[i] = 0x3f3f3f3f;
		L[i] = i * size, R[i] = i * size + size - 1;
		if(i == bnum - 1) R[i] = n - 1;
		for(int j=L[i]; j<=R[i]; j++) v[i].push_back(a[j]);
		sort(v[i].begin(), v[i].end());
	}
	while(m--){
		int op, l, r, k;
		scanf("%d%d%d%d", &op, &l, &r, &k);
		l--, r--;
		if(op == 1) update(l, r, k);
		else printf("%d\n", query(l, r, k));
	}
}
发布了221 篇原创文章 · 获赞 220 · 访问量 2万+

おすすめ

転載: blog.csdn.net/Scar_Halo/article/details/104095690