一.4前缀和和差分

前缀和:求l到r 的和

差分:求l到r 的都减去3的原数组 

a的逐个差为b,b的前缀和为a

//1,求a3到ak,即Sk-S2
#include
using namespace std;
const int N=100010;
int a[N],s[N];
int main()
{
	int n,m;
	cin>>n>>m; 
	s[0]=0;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		s[i]=s[i-1]+a[i];//s0+a1.s1+a2
	}
	while(m--)
	{
		int l,r;
		cin>>l>>r;
		cout<

一.4前缀和和差分_第1张图片

称为预处理

差分

一.4前缀和和差分_第2张图片

叫区间修改

一.4前缀和和差分_第3张图片

一.4前缀和和差分_第4张图片

差分构建
,就是每两个数字的差值是差分的值。一.4前缀和和差分_第5张图片一个一个减一个一个加一.4前缀和和差分_第6张图片

  • 输入原数组。
  • 差分。每两个数字的差值是差分的值
  • 进行区间修改(本后加减)
  • 求前缀和
  • 再用前缀和打印原数组

6   2
413527
为6个数,进行两次加减

再输入* * *几到几    加减几

  • 注意朝向一.4前缀和和差分_第7张图片
  • 注意在序号在线上,还是格子上
  •  因为二次循环第一个循环是行。所以有的把(1.2)为第一行第二列,有的(1.2)为列

  二位差分题目来源:

P5542 [USACO19FEB] Painting The Barn S - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

教程:冯老师教信奥

 二位差分:因为涂色的设为1,然后弄差分。若不设置为1那么用公式一.4前缀和和差分_第8张图片一.4前缀和和差分_第9张图片即为差分的规律。


//解题二维
//这里的i.j都为行列号
#include
using namespace std;
const int MAXN(1e3);
//int a[MAXN+5][MAXN+5];
int b[MAXN+5][MAXN+5];

int main(){
	int n,k;
	cin>>n>>k;
	while(n--){
		int x1,y1,x2,y2;
		cin>>x1>>y1>>x2>>y2;
		b[x1+1][y1+1]++;//给的是坐标不是第几行。我们要化为行列数。
		b[x1+1][y2+1]--;
		b[x2+1][y1+1]--;
		b[x2+1][y2+1]++;
	}
	int ans(0);
	for(int i=1;i<=MAXN;i++){
		for(int j=1;j<=MAXN;j++){
			b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
			if(b[i][j]==k){
				ans++;
			}
		}
	}
	cout<
//using namespace std;
//const int MAXN(1e3);
//int a[MAXN+5][MAXN+5];
int b[MAXN+5][MAXN+5];
//
//int main(){
//	int n,k;
//	cin>>n>>k;
//	while(n--){
//		int x1,y1,x2,y2;
//		cin>>x1>>y1>>x2>>y2;
//		for(int i=x1+1;i<=x2;i++){			
//给的是坐标不是第几行,行.i=x1+1或者是i<=x2-1前面不动。==============我们要化为行列数。
//			for(int j=y1+1;j<=y2;j++){
//				a[i][j]++;
//			}
//		}
//	}
//	int ans(0);
//	for(int i=1;i<=MAXN;i++){
//		for(int j=1;j<=MAXN;j++){	
//			if(a[i][j]==k){
//				ans++;
//			}
//		}
//	}
//	cout<

 注意:给的是坐标不是第几行,行.i=x1+1或者是i<=x2-1前面不动。==============我们要化为行列数。


ycx的

为什么要差分:要求a【l到r】都加c:al+c......ar+c时间是O(n)

若差分就是O(1)


一.4前缀和和差分_第10张图片S(i,j)=S(i-1,j)+S(i,j-1)-S(i-1,j-1)+a(i,j)

 一.4前缀和和差分_第11张图片

x1,y1到x2,y2的坐里面的求和

一维差分

一.4前缀和和差分_第12张图片

 输入样例:

6 3      n,m
1 2 2 1 2 1        整数序列        
1 3 1         m行个lrc
3 5 1
1 6 1

输出样例:

3 4 5 3 4 2

//1acw一维差分
#include 
#include
using namespace std;

const int N=100010;

int n,m;
int a[N],b[N];

void insert(int l,int r,int c)//不应该叫插入.应该区间修改得到b
{
  b[l]+=c;
  b[r+1]-=c;//因为insert(i,i,a[i])差分数组 b 的定义是:b[i] = a[i] - a[i-1],其中 a[0] = 0。
}
  int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);//数组
    for(int i=1;i<=n;i++)insert(i,i,a[i]);//得到b
    while(m--)//m行
    {
      int l,r,c;
      scanf("%d%d%d", &l, &r, &c);
      insert(l,r,c);//区间修改
    }

    for(int i=1;i<=n;i++)b[i]+=b[i-1];//b差分后自己弄前缀和
    for(int i=1;i<=n;i++)printf("%d ",b[i]);
  return 0;
}

二维差分

本来要枚举所有元素,现在只要四个元素

初始化很简单,b全部设置为0,再把a插进去

一.4前缀和和差分_第13张图片

输入 

 3 4 3  nmq


1 2 2 1  行m个整数
3 2 2 1
1 1 1 1


1 1 2 2 1    5个整数x1y1x2y2c
1 3 2 3 2
3 1 3 4 1

 输出

2 3 4 1
4 3 4 1
2 2 2 2

//二维
#include 
//#include 
//#include 
using namespace std;
 
const int N = 1010;
int a[N][N],b[N][N];
 
void change(int x1,int y1,int x2,int y2,int add)
{
    b[x1][y1] += add;
    b[x2+1][y1] -= add;
    b[x1][y2+1] -= add;
    b[x2+1][y2+1] += add;
}
int main()
{
    int n,m,x;
    cin >> n >> m >>x;
    for (int i = 1; i <= n; i ++ )//n行
        for (int j = 1; j <= m; j ++ ){//m列
            scanf("%d", &a[i][j]);
            change(i,j,i,j,a[i][j]);//a和把a加进去放在一个循环
        }
        
    int x1,x2,y1,y2,add;
    for (int i = 0; i < x; i ++ ){//相当于一个while函数
        scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &add);
        change(x1, y1, x2, y2, add);
    }
    for (int i = 1; i <= n; i ++ ){
        for (int j = 1; j <= m; j ++ ){//经典行列循环.每行都要做的事
            b[i][j] += b[i-1][j]+b[i][j-1]-b[i-1][j-1];//b差分后自己弄前缀和
            cout << b[i][j] << ' ';
        }
        cout << endl;
    }
    return 0;
}

你可能感兴趣的:(算法,算法,c++,图论)