【算法2-2】线性复杂度优化 / 离散化

P1950 长方形

题目链接:P1950 长方形 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <stack>
#include <cstring>
using namespace std;
char a[1010][1010];
int h[1010], g1[1010], g2[1010];

int main() {
	long long n, m, ans = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i] + 1;
		for (int j = 1; j <= m; j++) {
			if (a[i][j] == '*') {
				h[j] = 0;
			} else {
				h[j]++;
			}
		}
		memset(g1, 0, sizeof(g1));
		memset(g2, 0, sizeof(g2));
		stack<int>s;
		for (int j = 1; j <= m; j++) {
			while (!s.empty() && h[s.top()] > h[j]) {
				g2[s.top()] = j - 1;
				s.pop();
			}
			s.push(j);
		}
		while (!s.empty()) {
			g2[s.top()] = m;
			s.pop();
		}
		for (int j = m; j >= 1; j--) {
			while (!s.empty() && h[s.top()] >= h[j]) {
				g1[s.top()] = j + 1;
				s.pop();
			}
			s.push(j);
		}
		while (!s.empty()) {
			g1[s.top()] = 1;
			s.pop();
		}
		for (int j = 1; j <= m; j++) {
			ans += (j - g1[j] + 1) * (g2[j] - j + 1) * h[j];
		}
	}
	cout << ans;
	return 0;
}

P2032 扫描

题目链接:P2032 扫描 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <deque>
using namespace std;
int a[2000010];
deque<int>d;

int main() {
	int n, k;
	cin >> n >> k;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= n; i++) {
		while (!d.empty() && i - d.front() >= k) {
			d.pop_front();
		}
		while (!d.empty() && a[d.back()] < a[i]) {
			d.pop_back();
		}
		d.push_back(i);
		if (i >= k) {
			cout << a[d.front()] << endl;
		}
	}
	return 0;
}

参考博客:算法学习笔记(66): 单调队列 - 知乎 (zhihu.com)

P1440 求m区间内的最小值

题目链接:P1440 求m区间内的最小值 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <deque>
using namespace std;
int a[2000010];
deque<int>d;

int main() {
	int n, m;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
	cout << 0 << endl;
	for (int i = 1; i <= n - 1; i++) {
		while (!d.empty() && i - d.front() >= m) {
			d.pop_front();
		}
		while (!d.empty() && a[d.back()] > a[i]) {
			d.pop_back();
		}
		d.push_back(i);
		printf("%d\n", a[d.front()]);
	}
	return 0;
}

P1886 滑动窗口 /【模板】单调队列

题目链接:P1886 滑动窗口 /【模板】单调队列 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <deque>
using namespace std;
int a[1000010];
deque<int>d1, d2;

int main() {
	int n, k;
	cin >> n >> k;
	for (int i = 1; i <= n; i++) {
		scanf("%d", &a[i]);
	}
	for (int i = 1; i <= n; i++) {
		while (!d1.empty() && i - d1.front() >= k) {
			d1.pop_front();
		}
		while (!d1.empty() && a[d1.back()] > a[i]) {
			d1.pop_back();
		}
		d1.push_back(i);
		if (i >= k) {
			printf("%d ", a[d1.front()]);
		}
	}
	cout << endl;
	for (int i = 1; i <= n; i++) {
		while (!d2.empty() && i - d2.front() >= k) {
			d2.pop_front();
		}
		while (!d2.empty() && a[d2.back()] < a[i]) {
			d2.pop_back();
		}
		d2.push_back(i);
		if (i >= k) {
			printf("%d ", a[d2.front()]);
		}
	}
	return 0;
}

P3143 [USACO16OPEN]Diamond Collector S

题目链接:P3143 [USACO16OPEN]Diamond Collector S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <algorithm>
using namespace std;
int a[50005], b[50005];

int main() {
	int n, k, t = 0, le = 0, ans = 0;
	cin >> n >> k;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
	}
	sort(a, a + n);
	for (int i = 0; i < n; i++) {
		while (t < n && a[t] - a[i] <= k) {
			t++;
		}
		b[t] = max(b[t], t - i);
		le = max(le, b[i]);
		ans = max(ans, le + t - i);
	}
	cout << ans;
	return 0;
}

P1638 逛画展

题目链接:P1638 逛画展 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <deque>
using namespace std;
int c[1000010], d[2010], minn = 1 << 30;
deque<int>q;

int main() {
	int n, m, a, b, cnt = 0;
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> c[i];
		if (!d[c[i]]) {
			cnt++;
		}
		d[c[i]]++;
		q.push_back(i);
		while (!q.empty() && d[c[q.front()]] > 1) {
			d[c[q.front()]]--;
			q.pop_front();
		}
		if (cnt == m && minn > q.size()) {
			minn = q.size();
			a = q.front();
			b = q.back();
		}
	}
	cout << a << ' ' << b;
	return 0;
}

P1419 寻找段落

题目链接:P1419 寻找段落 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <deque>
#include <cstring>
#include <iomanip>
using namespace std;
int n, s, t;
double a[100010];
double sum[100010];

bool check(double x) {
	memset(sum, 0, sizeof(sum));
	for (int i = 1; i <= n; i++) {
		sum[i] = sum[i - 1] + a[i] - x;
	}
	deque<int>q;
	for (int i = 1; i <= n; i++) {
		if (i >= s) {
			while (!q.empty() && sum[q.back()] > sum[i - s]) {
				q.pop_back();
			}
			q.push_back(i - s);
		}
		if (!q.empty() && q.front() < i - t) {
			q.pop_front();
		}
		if (!q.empty() && sum[i] - sum[q.front()] >= 0) {
			return true;
		}
	}
	return false;
}

int main() {
	cin >> n >> s >> t;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	double Left = -10000, Right = 10000;
	while (Right - Left > 1e-5) {
		double mid = (Left + Right) / 2;
		if (check(mid)) {
			Left = mid;
		} else {
			Right = mid;
		}
	}
	cout << setprecision(3) << fixed << Left;
	return 0;
}

P2882 [USACO07MAR]Face The Right Way G

题目链接:P2882 [USACO07MAR]Face The Right Way G - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <cstring>
using namespace std;
int a[5005], d[5005];

int main() {
	int n, ansm = 1 << 30, ansk;
	char c;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> c;
		if (c == 'F') {
			a[i] = 1;
		}
	}
	for (int k = 1; k <= n; k++) {
		memset(d, 0, sizeof(d));
		bool flag = 1;
		int now = 0, cnt = 0;
		for (int i = 1; i <= n; i++) {
			now ^= d[i];
			if (now ^ a[i] == 0) {
				if (i + k - 1 > n) {
					flag = 0;
					break;
				}
				now ^= 1;
				d[i + k] ^= 1;
				cnt++;
			}
		}
		if (flag && ansm > cnt) {
			ansm = cnt;
			ansk = k;
		}
	}
	cout << ansk << ' ' << ansm;
	return 0;
}

参考博客:差分 --算法竞赛专题解析(32)_罗勇军的博客-CSDN博客_差分算法 

P1147 连续自然数和

题目链接:P1147 连续自然数和 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
using namespace std;

int main() {
	int m;
	cin >> m;
	for (int i = 1; i <= m / 2; i++) {
		int sum = 0, j;
		for (j = i; j <= m; j++) {
			sum += j;
			if (sum >= m) {
				break;
			}
		}
		if (sum == m) {
			cout << i << ' ' << j << endl;
		}
	}
	return 0;
}

P4086 [USACO17DEC]My Cow Ate My Homework S

题目链接:P4086 [USACO17DEC]My Cow Ate My Homework S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <algorithm>
using namespace std;
double a[100010], sum[100010], minn[100010];
double avg[100010];

int main() {
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		minn[i] = 10010;
	}
	minn[n + 1] = 10010;
	for (int i = n; i >= 2; i--) {
		minn[i] = min(minn[i + 1], a[i]);
		sum[i] = sum[i + 1] + a[i];
		if (i != n) {
			avg[i] = (sum[i] - minn[i]) / (double)(n - i);
		}
	}
	double maxx = 0;
	for (int i = 2; i <= n - 1; i++) {
		maxx = max(maxx, avg[i]);
	}
	for (int i = 2; i <= n - 1; i++) {
		if (maxx == avg[i]) {
			cout << i - 1 << endl;
		}
	}
	return 0;
}

P3124 [USACO15OPEN]Trapped in the Haybales S

题目链接:P3124 [USACO15OPEN]Trapped in the Haybales S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <algorithm>
using namespace std;

struct A {
	int pos, size;
} a[100010];

bool cmp(A a1, A a2) {
	return a1.pos < a2.pos;
}

int main() {
	int n, b, now, ans = 1 << 30;
	cin >> n >> b;
	for (int i = 1; i <= n; i++) {
		cin >> a[i].size >> a[i].pos;
	}
	sort(a + 1, a + n + 1, cmp);
	for (int i = 1; i <= n; i++) {
		if (a[i].pos > b) {
			now = i;
			break;
		}
	}
	int l = now - 1, r = now, d = a[r].pos - a[l].pos;
	while (l >= 1 && r <= n) {
		if (a[l].size >= d && a[r].size >= d) {
			cout << 0;
			return 0;
		}
		if (a[r].size < d) {
			r++;
			d += a[r].pos - a[r - 1].pos;
			continue;
		}
		if (a[l].size < d) {
			ans = min(ans, d - a[l].size);
			l--;
			d += a[l + 1].pos - a[l].pos;
		}
	}
	l = now - 1;
	r = now;
	d = a[r].pos - a[l].pos;
	while (l >= 1 && r <= n) {
		if (a[l].size >= d && a[r].size >= d) {
			cout << 0;
			return 0;
		}
		if (a[l].size < d) {
			l--;
			d += a[l + 1].pos - a[l].pos;
			continue;
		}
		if (a[r].size < d) {
			ans = min(ans, d - a[r].size);
			r++;
			d += a[r].pos - a[r - 1].pos;
		}
	}
	if (ans == (1 << 30)) {
		cout << -1;
	} else {
		cout << ans;
	}
	return 0;
}

P1496 火烧赤壁

题目链接:P1496 火烧赤壁 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

#include <iostream>
#include <algorithm>
using namespace std;
int a[20010], b[20010];

int main() {
	int n, ans = 0;
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> a[i] >> b[i];
	}
	sort(a, a + n);
	sort(b, b + n);
	for (int i = 0; i < n; i++) {
		ans += b[i] - a[i];
		if (i != n - 1) {
			if (b[i] > a[i + 1]) {
				ans -= b[i] - a[i + 1];
			}
		}
	}
	cout << ans;
	return 0;
}

P1884 [USACO12FEB]Overplanting S

题目链接:P1884 [USACO12FEB]Overplanting S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

参考博客:扫描线 - Ling_Lover - 博客园 (cnblogs.com) 

【算法】线段树详解__Alexander_的博客-CSDN博客_线段树详解 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值