L'idée de base de la somme des préfixes

(1) Définition de la somme des préfixes

    Supposons qu'il y ait une chaîne ABCDE, alors A, AB, ABC, ABCD, ABCDE sont les préfixes de ce mot, en commençant par le premier caractère et en remontant dans l'ordre. Et E, ED, EDC, EDCB, EDCBA sont appelés suffixes de ce mot.

    Ensuite, pour le préfixe d'un tableau de type int, tel que le tableau a=[0,12,62,33,4,55], nous maintenons un tableau sum composé de la somme du préfixe, et sum[i] représente un [0 dans le tableau ]~a[i] et. Où a[0] est par défaut égal à 0, si :

  • somme[0]=a[0]=0
  • somme[1]=a[0]+a[1]
  • somme[2]=a[0]+a[1]+a[2]
  • somme[3]=a[0]+a[1]+a[2]+a[3]
  • somme[4]=a[0]+a[1]+a[2]+a[3]+a[4]

  Alors sum est le préfixe et le tableau du tableau a.

(2) Le rôle de la somme des préfixes

  La somme des préfixes peut être stockée par prétraitement (maintien lors de la saisie), ce qui peut réduire considérablement la complexité du monde de la requête. Parce que le but principal de la somme des préfixes est de trouver la taille de la somme des sous-tableaux. Par exemple, la somme des éléments a[1] à a[3] : a[1]+a[2]+a[3], cette boucle for prend un temps O(n), et le préfixe et sum[ 3] -sum[0] à résoudre est la complexité de O(1), pourquoi sum[3]-sum[0] est la somme de a[1] à a[3] ?

  Laissez-moi vous expliquer, donnez un exemple plus frappant, trouvez la somme des éléments a[3] à a[5] : a[3]+a[4]+a[5], la somme du préfixe est sum[5] -sum [2], pourquoi ? Démontons-le :

somme[5]=a[0]+a[1]+a[2]+a[3]+a[4]+a[5] ;

somme[2]=a[0]+a[1]+a[2] ;

  Ne voyant rien, les trois précédents a[0]+a[1]+a[2] peuvent être décalés, cela devient a[3]+a[4]+a[5], donc en utilisant le préfixe somme Pensée, le temps la complexité est optimisée au maximum.

(3) Application des préfixes et

  Utilisons une question pour illustrer l'application de la somme des préfixes.

  Étant donné un tableau d'entiers de longueur n et un entier k, vous devez trouver le nombre de sous-tableaux consécutifs dans le tableau qui totalisent k,

Échantillon de test:

entrer:

5 3
1 1 2 1 1

sortir:

2

  Idée 1 :

    Utilisez la boucle for pour énumérer violemment les sous-tableaux, et sum + count, la complexité temporelle est O(n^3). (Si les données sont supérieures à 100, cette idée est définitivement Time Limit Exceeded (temps supplémentaire), elle doit donc être optimisée) !

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int a[n],sum=0; //定义数组和计数器 
	for(int i=0;i<n;i++) //for循环输入 
	  scanf("%d",a[i]); //输入下标为i的数 
	for(int i=0;i<n;i++){ //区间i枚举 
		for(int j=0;j<n;j++){ //区间j枚举 
			int ans=0; //区间和计数数组 
			for(int x=i;x<=j;x++) //求出区间[i,j]的和 
			  ans+=a[i]; //计数 
			if(ans==k) //比较 
			  sum++; //计数	  
		}
	}
	cout<<sum<<endl; //输出 
	return 0;
}

Idée 2 :

  Nous pouvons également utiliser la somme des préfixes pour résoudre ce problème.Tout d'abord, prétraitez la somme du tableau de préfixes de a, calculez la somme des sous-tableaux à chaque fois, puis effectuez l'énumération des intervalles à double boucle, puis comparez-la avec k. La complexité temporelle est O (n ^ 2) (si les données ne sont pas supérieures à 1500, elles peuvent être AC et il y a encore de la place pour l'optimisation).

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans 
	sum[0]=0; //将下标为0的地址初始化为0  
	for(int i=1;i<=n;i++){ //进行循环n次读入 
		int a; //定义 
		scanf("%d",&a); //输入 
		sum[i]=sum[i-1]+a; //求前缀和 
	}
	for(int i=1;i<=n;i++) //区间枚举i 
	  for(int j=0;j<n;j++) //区间枚举j 
	    if(sum[i]-sum[j]==k) //求出区间[i,j]的和与k比较 
	      ans++; //计数器加1 
	cout<<ans<<endl; //输出计数器 
	return 0; //结束 
}

Idée 3 :

  Nous pouvons utiliser map (une classe définie par la bibliothèque STL), préfixer et optimiser. Dans l'idée d'utiliser le préfixe sum seul, on demande si la somme d'un sous-tableau avec l'indice final i est k, on doit parcourir j de 0 à i-1 pour trouver s'il y a sum[i]-k = somme[j]. Ensuite, nous n'utilisons map que pour enregistrer la somme des préfixes des premiers i éléments, enregistrer la valeur de la somme des préfixes avant le nombre d'occurrences (>i), et enfin juger si la carte contient sum[i]-k.

  La complexité temporelle est O(n), ce qui est déjà très rapide, et les données peuvent être AC si elles atteignent plusieurs millions.

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n,k; //定义 
	scanf("%d%d",&n,&k); //输入 
	int sum[n+1]={0},ans=0; //定义前缀和数组sum和计数器ans 
	sum[0]=0; //将下标为0的地址初始化为0  
	map<int,int> p; //定义map 
	for(int i=1;i<=n;i++){ //进行循环n次读入 
		int a; //定义 
		scanf("%d",&a); //输入 
		sum[i]=sum[i-1]+a; //求前缀和 
		p[sum[i]]++; //进行存储 
	}
	for(int i=0;i<n;i++) //进行区间判断 
	  ans+=p[sum[i]+k]; //计数 
	cout<<ans<<endl; //输出 
	return 0; //结束 
}

Résumer:

  La somme des préfixes est un algorithme très utile qui peut considérablement optimiser la complexité temporelle. J'espère que vous pourrez en apprendre davantage. Je parlerai de quelques exercices de somme des préfixes dans les prochains articles.

Je suppose que tu aimes

Origine blog.csdn.net/wo_ai_luo_/article/details/129819793
conseillé
Classement