洛谷 P3709 大爷的字符串题 解题报告

洛谷 P3709 大爷的字符串题 解题报告

[link](P3709 大爷的字符串题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn))

Solutions

我们手玩一下,可将题意转化为 求区间众数的出现次数

我们贪心地想,最优情况一定是将原数列分割成几个单调递增的数列,数列个数即为 众数出现次数减去数列长度

Details

注意题面的\(rp\)是从0开始减的,所以输出\(-ans[i]\)

Code

P3709:

#include <bits/stdc++.h>

using namespace std;

const int MN = 2e5 + 5;

int n, m, block, sum;
int a[MN], date[MN], cnt[MN], num[MN], ans[MN];
struct Query {
	int l, r, id;
	bool operator < (const Query &x) const {
		return l / block != x.l / block ? l < x.l : l / block & 1 ? r < x.r : r > x.r;
	}
} q[MN];

void add(int x) {
	num[cnt[x]]--, cnt[x]++, num[cnt[x]]++;
	while (num[sum + 1]) sum++;
}

void del(int x) {
	num[cnt[x]]--, cnt[x]--, num[cnt[x]]++;
	while (!num[sum]) sum--;
}

signed main() {
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n >> m; block = sqrt(n);
	for (int i = 1; i <= n; ++i) cin >> a[i], date[i] = a[i];
	sort(date + 1, date + 1 + n);
	int qwq = unique(date + 1, date + 1 + n) - date - 1;
	for (int i = 1; i <= n; ++i) a[i] = lower_bound(date + 1, date + 1 + qwq, a[i]) - date;
	for (int i = 1; i <= m; ++i) {
		cin >> q[i].l >> q[i].r;
		q[i].id = i;
	}
	sort(q + 1, q + 1 + m);
	for (int i = 1, l = 1, r = 0; i <= m; ++i) {
		while (l > q[i].l) add(a[--l]);
		while (r < q[i].r) add(a[++r]);
		while (l < q[i].l) del(a[l++]);
		while (r > q[i].r) del(a[r--]);
		ans[q[i].id] = sum;
	}
	for (int i = 1; i <= m; ++i) cout << -ans[i] << '\n';
	return 0;
}

CF1514D

#include <bits/stdc++.h>

using namespace std;

const int MN = 3e5 + 5;

int n, m, block, sum;
int a[MN], date[MN], cnt[MN], num[MN], ans[MN];
struct Query {
	int l, r, id;
	bool operator < (const Query &x) const {
		return l / block != x.l / block ? l < x.l : l / block & 1 ? r < x.r : r > x.r;
	}
} q[MN];

void add(int x) {
	num[cnt[x]]--, cnt[x]++, num[cnt[x]]++;
	while (num[sum + 1]) sum++;
}

void del(int x) {
	num[cnt[x]]--, cnt[x]--, num[cnt[x]]++;
	while (!num[sum]) sum--;
}

signed main() {
	ios::sync_with_stdio(false), cin.tie(0);
	cin >> n >> m; block = sqrt(n);
	for (int i = 1; i <= n; ++i) cin >> a[i], date[i] = a[i];
	sort(date + 1, date + 1 + n);
	int qwq = unique(date + 1, date + 1 + n) - date - 1;
	for (int i = 1; i <= n; ++i) a[i] = lower_bound(date + 1, date + 1 + qwq, a[i]) - date;
	for (int i = 1; i <= m; ++i) {
		cin >> q[i].l >> q[i].r;
		q[i].id = i;
	}
	sort(q + 1, q + 1 + m);
	for (int i = 1, l = 1, r = 0; i <= m; ++i) {
		while (l > q[i].l) add(a[--l]);
		while (r < q[i].r) add(a[++r]);
		while (l < q[i].l) del(a[l++]);
		while (r > q[i].r) del(a[r--]);
		ans[q[i].id] = sum * 2 - (q[i].r - q[i].l + 1);
	}
	for (int i = 1; i <= m; ++i) cout << max(1, ans[i]) << '\n';
	return 0;
}

Data

莫队求区间众数:莫队求区间众数 D. Cut and Stick - EchoZQN - 博客园 (cnblogs.com)

题意转化思路参考:题解 P3709 【大爷的字符串题】 - 中国飞鱼 的博客 - 洛谷博客 (luogu.com.cn)

posted @ 2022-06-19 12:10  zjsqwq  阅读(41)  评论(0)    收藏  举报