前缀和与差分

一、HJ浇花

题目链接:https://ac.nowcoder.com/acm/contest/322/M
在这里插入图片描述
代码:

#include<bits/stdc++.h>

using namespace std;

const int maxsize1 = 1e6+10;
const int maxsize2 = 2e5+10;

int a[maxsize1];
int cant[maxsize2];//cant[i]表示被浇了i次水的花有多少盆 

int main() {
	int n;
	scanf("%d",&n);
	memset(a,0,sizeof(a));
	memset(cant,0,sizeof(cant));
	for(int j =1;j<=n;j++) { 
		int l,r;
		scanf("%d%d",&l,&r);
		//差分初始化
		a[l]++;
		a[r+1]--;
	}
	for(int i=1;i<maxsize1;i++) { 
		a[i]+=a[i-1];//前缀和,a[i]表示编号为0~i的花总共被浇了多少次 
	}
	for(int i=0;i<maxsize1;i++) {
		cant[a[i]]++;//依次遍历,浇了a[i]次的+1 
	}
	for(int i=1;i<=n;i++) {
		printf("%d ",cant[i]);//输出被浇了i次水的花有多少盆
	}
	return 0;
}

二、非零段划分

题目:ccf-csp的202109-2题——非零段划分
在这里插入图片描述
题解:
严谨点说这道题其实用的是差分+后缀和的思想(后缀和基本和前缀和类似)
代码:

#include<bits/stdc++.h>

using namespace std;

const int maxsize = 5e5+10;

int a[maxsize];
int cnt[10010];//p为i时非零段的个数 

int main() {
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%d",&a[i]);
	}
	n = unique(a+1,a+1+n)-a-1;
	memset(cnt,0,sizeof(cnt));
	a[0]=a[n+1]=0;
	for(int i=1;i<=n;i++) {
		int x=a[i-1],y=a[i],z=a[i+1];
		if(y>x&&y>z) cnt[y]++;
		else if(y<x&&y<z) cnt[y]--;
	}
	int sum = 0;
	int bsum=0;    //记录后缀和 
	for(int i=10010;i>0;i--) {
		bsum+=cnt[i];
		sum = max(sum,bsum); 
	}
	printf("%d",sum);
	return 0;
}

三、邻域均值

ccf-csp的202104-2题
在这里插入图片描述

#include<bits/stdc++.h>

using namespace std;

int a[610][610];
int b[610][610];//前缀和

int main() {
	int n, l, r, t;
	int sum = 0;
	scanf("%d%d%d%d", &n, &l, &r, &t);
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			scanf("%d", &a[i][j]);
		}
	}

	for (int i = 0; i <= n; i++) {
		for (int j = 0; j <= n; j++) {
			if (i == 0 || j == 0) {
				b[i][j] = 0;
			}
		}
	}

	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			b[i][j] = b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1] + a[i][j];
		}
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			int x;
			int x1, x2, y1, y2;
			if (i + r > n) {
				x2 = n;
			} else {
				x2 = i + r;
			}
			if (j + r > n) {
				y2 = n;
			} else {
				y2 = j + r;
			}
			if (i - r - 1 < 0) {
				x1 = 0;
			} else {
				x1 = i - r - 1;
			}
			if (j - r - 1 < 0) {
				y1 = 0;
			} else {
				y1 = j - r - 1;
			}
			int cunt = (x2 - x1) * (y2 - y1);
			x = (b[x2][y2] - b[x1][y2] - b[x2][y1] + b[x1][y1]);
			if (x <= t * cunt)sum++;
		}
	}
	printf("%d\n", sum);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值