前缀和与差分的使用技巧

前缀和与差分是算法中常用的技巧,可以有效的降低算法复杂度,一些题目看似是线段树的问题,实际可以通过前缀和与差分求解。相对于线段树,前缀和与差分代码更简洁。首先引用两篇博客:
[1] https://blog.csdn.net/XT_NOI/article/details/72715904
[2] https://blog.csdn.net/k_r_forever/article/details/81775899

最近做了一些相关的题目:

  1. 西南民族大学第十届校赛(同步赛),M题:HJ浇花,https://ac.nowcoder.com/acm/contest/322/M
#include 
#include 
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;
}
  1. 杭电OJ1556,Color the ball,http://acm.hdu.edu.cn/showproblem.php?pid=1556
#include 
#include 
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;
}
  1. 杭电OJ5327,Olympiad,http://acm.hdu.edu.cn/showproblem.php?pid=5327
#include 
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;
}
  1. 杭电OJ5480,Conturbatio,http://acm.hdu.edu.cn/showproblem.php?pid=5480
    这道题是二维前缀和,实际上是将每一个車(x,y)提升到第一行和第一列
#include 
#include 
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;
}

你可能感兴趣的:(Algorithm,前缀和,差分)