蒟蒻求助
查看原帖
蒟蒻求助
201007
Leasier楼主2021/7/9 22:09

RT,本蒟蒻写的是带修莫队,样例 AC,但全部 WA /kk

代码:

#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;

typedef struct {
	int pos;
	int val;
} Modification;

typedef struct {
	int id;
	int opt;
	int l;
	int r;
	int time;
	int k;
} Query;

int block1;
int a[50007], b[100007], belong[100007], lft[327], rt[327], cnt[100007], sum[327], ans[50007];
Modification modification[50007];
Query query[50007];

bool operator <(const Query a, const Query b){
	if (a.l / block1 != b.l / block1) return a.l < b.l;
	if (a.r / block1 != b.r / block1) return a.r < b.r;
	return a.time < b.time;
}

inline void add(int x){
	cnt[x]++;
	sum[belong[x]]++;
}

inline void del(int x){
	cnt[x]--;
	sum[belong[x]]--;
}

inline void modify(int x, int time){
	if (query[x].l <= modification[time].pos && modification[time].pos <= query[x].r){
		del(a[modification[time].pos]);
		add(modification[time].val);
	}
	swap(a[modification[time].pos], modification[time].val);
}

inline int brute_force_get_sum(int l, int r){
	int ans = 0;
	for (register int i = l; i <= r; i++){
		ans += cnt[i];
	}
	return ans;
}

inline int get_sum(int l, int r){
	int ans = brute_force_get_sum(l, min(r, rt[belong[l]]));
	if (belong[l] != belong[r]) ans += brute_force_get_sum(lft[belong[r]], r);
	for (register int i = belong[l] + 1; i < belong[r]; i++){
		ans += sum[i];
	}
	return ans;
}

inline int get_kth_number(int k, int n){
	if (k <= 0 || k > get_sum(1, n)) return -1;
	int l = 1, r = n, ans;
	while (l <= r){
		int mid = (l + r) >> 1;
		if (get_sum(1, mid) >= k){
			r = mid - 1;
			ans = mid;
		} else {
			l = mid + 1;
		}
	}
	return ans;
}

inline int get_prev(int k, int n){
	return get_kth_number(get_sum(1, k - 1), n);
}

inline int get_next(int k, int n){
	return get_kth_number(get_sum(1, k) + 1, n);
}

int main(){
	int n, m, block2, modification_cnt = 0, val_cnt, k, query_cnt = 0;
	cin >> n >> m;
	val_cnt = n;
	for (register int i = 1; i <= n; i++){
		cin >> a[i];
		b[i] = a[i];
	}
	for (register int i = 1; i <= m; i++){
		int opt;
		cin >> opt;
		if (opt == 3){
			modification_cnt++;
			cin >> modification[modification_cnt].pos >> modification[modification_cnt].val;
			b[++val_cnt] = modification[modification_cnt].val;
		} else {
			query_cnt++;
			query[query_cnt].opt = opt;
			cin >> query[query_cnt].l >> query[query_cnt].r >> query[query_cnt].k;
			query[query_cnt].id = query_cnt;
			query[query_cnt].time = modification_cnt;
			if (opt != 2) b[++val_cnt] = query[query_cnt].k;
		}
	}
	block1 = ceil(n / cbrt(query_cnt));
	sort(b + 1, b + val_cnt + 1);
	val_cnt = unique(b + 1, b + val_cnt + 1) - b - 1;
	block2 = sqrt(val_cnt);
	k = (val_cnt - 1) / block2 + 1;
	for (register int i = 1; i <= n; i++){
		a[i] = lower_bound(b + 1, b + val_cnt + 1, a[i]) - b;
	}
	for (register int i = 1; i <= modification_cnt; i++){
		modification[i].val = lower_bound(b + 1, b + val_cnt + 1, modification[i].val) - b;
	}
	for (register int i = 1; i <= query_cnt; i++){
		if (query[i].opt != 2) query[i].k = lower_bound(b + 1, b + val_cnt + 1, query[i].k) - b;
	}
	for (register int i = 1; i <= val_cnt; i++){
		belong[i] = (i - 1) / block2 + 1;
	}
	for (register int i = 1; i <= k; i++){
		lft[i] = (i - 1) * block2 + 1;
		rt[i] = min(i * block2, val_cnt);
	}
	sort(query + 1, query + query_cnt + 1);
	for (register int i = 1, j = 1, x = 0, y = 0; i <= query_cnt; i++){
		while (j > query[i].l) add(a[--j]);
		while (x < query[i].r) add(a[++x]);
		while (j < query[i].l) del(a[j++]);
		while (x > query[i].r) del(a[x--]);
		while (y < query[i].time) modify(i, ++y);
		while (y > query[i].time) modify(i, y--);
		if (query[i].opt == 1){
			ans[query[i].id] = get_sum(1, query[i].k);
		} else if (query[i].opt == 2){
			ans[query[i].id] = b[get_kth_number(query[i].k, val_cnt)];
		} else if (query[i].opt == 4){
			int pos = get_prev(query[i].k, val_cnt);
			ans[query[i].id] = pos == -1 ? -0x7fffffff : b[pos];
		} else {
			int pos = get_next(query[i].k, val_cnt);
			ans[query[i].id] = pos == -1 ? 0x7fffffff : b[pos];
		}
	}
	for (register int i = 1; i <= query_cnt; i++){
		cout << ans[i] << endl;
	}
	return 0;
}
2021/7/9 22:09
加载中...