一类差分题的思考方式及经典例题
问题描述
这类题目一般都会给定一个整数序列和一个大定义域。定义一个与序列元素有关的函数,定义域是,值域是非负整数。
找到一个,使得最大。
思考方式
虽然的范围可能很大,但是的可能不多。因此我们只需要知道哪些的,且这些的值是多少即可。
这类题一般都会先考虑序列中元素对哪些有贡献,一个元素会使得一个区间上的答案同增或同减一个常数(通常就是)。比如:当,为贡献了。
因此可以使用差分维护这个过程,最后求前缀和并更新答案即可。
因此我们对于具体题目的考虑就是,什么样的元素会影响哪个区间。
典型例题
题意:是一个由个自然数(非负整数)组成的数组。我们称其中是一个非零段,当且仅当以下条件同时满足:;对于任意的整数,若,则;或;或。现在我们可以对数组进行如下操作:任选一个正整数,然后将中所有小于的数都变为。试选取一个合适的,使得数组中的非零段个数达到最大。若输入的所含非零段数已达最大值,可取,即不对做任何修改。
解题思路:在这道题中,表示非零段个数。我们现在考虑什么样的元素会影响哪个区间。对于相邻两个数,如果,为了让变为一个非零段的开始,我们需要把变为。而可以满足这个要求,也就是为这个区间上的都贡献了。因此,这样的元素会使得这个区间答案加。
注:岛(https://www.acwing.com/problem/content/2016/ )与本题几乎一样,只不过定义域更大,因此需要用map存差分。
代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N = 500010, M = 10010;
int n;
int a[N], b[M];
void insert(int l, int r)
{
b[l] ++, b[r + 1] --;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
int x;
scanf("%d", &x);
a[i] = x;
if(a[i] > a[i - 1]) insert(a[i - 1], a[i] - 1);
//如果选择[a[i - 1], a[i] - 1],那么第i个元素开始就称为了非零段
//因此区间内所有数字贡献+1
}
int ans = 0;
for(int i = 0; i < M; i ++) {
b[i] = b[i - 1] + b[i];
ans = max(ans, b[i]);
}
printf("%d\n", ans);
return 0;
}
- Robot Takahashi(https://atcoder.jp/contests/abc257/tasks/abc257_c)
题意:有一群大人和小孩,每个人都有一个高度。你需要划定一个高度标注,并且你认为大于等于的人都是大人,小于的都是小孩。问:找到一个,使得判断准确人数最多。
思路:在这道题中,表示判断准确人数。我们现在考虑什么样的元素会影响哪个区间。对于一个人,当处于哪个区间才能将其分对呢?如果这个人是大人,那么是可以分对的,对这个区间贡献;如果这个人是小孩,那么可以分对的,对这个区间贡献。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int N = 200010;
int n;
char s[N];
map<int, int> mp;
void insert(int l, int r)
{
mp[l] ++, mp[r + 1] --;
}
int main()
{
scanf("%d%s", &n, s + 1);
for(int i = 1; i <= n; i ++) {
int x;
scanf("%d", &x);
if(s[i] == '1') insert(0, x);
else insert(x + 1, 1e9);
}
int ans = 0, t = 0;
for(auto p : mp) {
t += p.second;
ans = max(ans, t);
}
printf("%d\n", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 按钮权限的设计及实现