前缀和与差分是算法中常用的技巧,可以有效的降低算法复杂度,一些题目看似是线段树的问题,实际可以通过前缀和与差分求解。相对于线段树,前缀和与差分代码更简洁。首先引用两篇博客:
[1] https://blog.youkuaiyun.com/XT_NOI/article/details/72715904
[2] https://blog.youkuaiyun.com/k_r_forever/article/details/81775899
最近做了一些相关的题目:
- 西南民族大学第十届校赛(同步赛),M题:HJ浇花,https://ac.nowcoder.com/acm/contest/322/M
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 2e6 + 5;
int cnt[maxn], prefix[maxn], a[maxn], n, l, r;
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> l >> r;
prefix[l] += 1;
prefix[r + 1] -= 1;
}
for (int i = 1; i < maxn; i++)
prefix[i] += prefix[i - 1];
for (int i = 0; i < maxn; i++)
cnt[prefix[i]]++;
for (int i = 1; i <= n; i++)
cout << cnt[i] << " ";
return 0;
}
- 杭电OJ1556,Color the ball,http://acm.hdu.edu.cn/showproblem.php?pid=1556
#include <iostream>
#include <string.h>
using namespace std;
const int maxn = 100005;
int pmax[maxn];
int main()
{
int N, a, b;
while (cin >> N && N)
{
memset(pmax, 0, sizeof(pmax));
for (int i = 1; i <= N; i++)
{
cin >> a >> b;
pmax[a]++;
pmax[b+1]--;
}
for (int i = 1; i <= N; i++)
{
pmax[i] += pmax[i - 1];
if (i < N)
cout << pmax[i] << " ";
else
cout << pmax[i] << endl;
}
}
return 0;
}
- 杭电OJ5327,Olympiad,http://acm.hdu.edu.cn/showproblem.php?pid=5327
#include <iostream>
using namespace std;
int T, l, r,pmax[100005];
int check(int x)
{
int digit[10] = { 0 };
while (x)
{
int c = x % 10;
if (digit[c])
return 0;
digit[c] = 1;
x /= 10;
}
return 1;
}
int main()
{
for (int i = 1; i <= 100005; i++)
pmax[i] = pmax[i - 1] + check(i);
cin >> T;
while (T--)
{
cin >> l >> r;
cout << pmax[r] - pmax[l - 1] << endl;
}
return 0;
}
- 杭电OJ5480,Conturbatio,http://acm.hdu.edu.cn/showproblem.php?pid=5480
这道题是二维前缀和,实际上是将每一个車(x,y)提升到第一行和第一列
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e5 + 5;
int x[N], y[N], t, n, m, p, q, x1, x2, y1, y2;
int main()
{
scanf("%d", &t);
while (t--)
{
scanf("%d%d%d%d", &n, &m, &p, &q);
memset(x, 0, sizeof(x));
memset(y, 0, sizeof(y));
for (int i = 1; i <= p; i++)
{
scanf("%d%d", &x1, &y1);
x[x1] = y[y1] = 1;
}
for (int i = 2; i <= n; i++)
x[i] += x[i - 1];
for (int i = 2; i <= m; i++)
y[i] += y[i - 1];
for (int i = 1; i <= q; i++)
{
scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
if (x[x2] - x[x1 - 1] == (x2 - x1 + 1) || y[y2] - y[y1 - 1] == (y2 - y1 + 1))
printf("Yes\n");
else
printf("No\n");
}
}
return 0;
}