首碼和

来源:https://www.cnblogs.com/momotrace/archive/2023/05/03/Prefix-sum.html
-Advertisement-
Play Games

首碼和 一、介紹 ~~首碼,顧名思義就是一個東西前面的點綴...~~(bushi 其實打比方來說就是:假如有一字元串ABCD,那麼他的首碼就是A、AB、ABC、ABCD這四個從新從第一個字母一次往後開始拼接的字元串。當然這是字元串。但首碼和一般應用於數組,對於給定的數組a=[1,2,3,4],他的前 ...


首碼和

一、介紹

首碼,顧名思義就是一個東西前面的點綴...(bushi

其實打比方來說就是:假如有一字元串ABCD,那麼他的首碼就是A、AB、ABC、ABCD這四個從新從第一個字母一次往後開始拼接的字元串。當然這是字元串。但首碼和一般應用於數組,對於給定的數組a=[1,2,3,4],他的前 i 項和sum[i]就表示數組中a[0]~a[i]的和,具體為:
sum[0]=a[0]
sum[1]=a[0]+a[1]
......
sum[i]=sum[0]+sum[1]+...+sum[i];

二、定義

定義:首碼和是指某一序列的前 n 項和

基於首碼和的使用,我們一般把首碼和分為一維首碼和二維首碼和

三、一維首碼和

定義

基於一維數組的首碼和就是原數組前n個元素的和

const int N = 10010;
 
int a[N]; //原數組a[]
int s[N]; //首碼和數組s[]
 
//根據定義 一維首碼和s[i]
s[i] = a[1] + a[2] + a[3] +...+ a[i];
 
//舉例 設i=3 根據上式可得
s[3] = a[1] + a[2] + a[3];
 
//根據上面舉例,可以再一步寫成
s[i] = s[i-1] + a[i]; 

需要註意的一點是:數組的下標都是從 1 開始的!!!

作用

主要作用是可以在O(1)時間情況下快速的求出任一區間[l,r]內的元素之和。

//例如求a[3]+...+a[10]之間的和,我們可以利用首碼和迅速求出:
  a[3]+...+a[10]
= (a[1]+a[2]+a[3]...+a[10]) - (a[1]+a[2])
= s[10] - s[2]
 
//根據上面舉例,我們可以推導出求某一區間[l,r]內的和的公式
  a[l]+a[l+1]+...+a[r-1]+a[r] 
= s[r] - s[l-1];

方法

一維數組求首碼和方法

int a[100],s[100];
for(int i = 1; i<= 99; i++)
{
    scanf("%d",&a[i]);
}
for(int i = 1; i<= 99; i++)
{
    s[i] = s[i-1]+a[i];
}

實戰演練!!!

「模板」首碼和

輸入n個數,給出m個詢問,詢問區間[x,y]的和。

輸入
  • 第一行為n和m,1<=n,m<=100000

  • 接下來一行為n個數,範圍在0~100000之間

  • 接下來m行,每行兩個數x,y,輸出第x個數到第y個數之間所有數的和。保證x<=y

輸出

m個輸出

樣例輸入
5 3
1 2 0 7 6
1 3
2 2
4 5
樣例輸出
3
2
13
代碼:
#include <bits/stdc++.h>
using namespace std;
int n,m;
long long a[100010],b[100010];//見註釋1
int main()
{
	cin >> n >> m;
	for(int i=1; i<=n;i++)
	{
		cin >> a[i];
	}
	b[0]=0;
	for(int i=1;i<=n;i++)
	{
		b[i]=b[i-1]+a[i];
	}
	while(m--)
	{
		int l,r;
		cin >> l >> r;
		cout << b[r] - b[l-1] << "\n";
	}
	return 0;
}

註釋①:測試範圍大image

四、二維首碼和

定義

基於二維數組的首碼和,它是指一個前 i 行和前 j 列的子矩陣的和

const int N =100010;
int a[N][N] //原二維數組
int s[N][N] //二維首碼和數組
 
//根據定義可得
s[i][j] = a[1][1] + a[1][2] + ... + a[1][j]+
          a[2][1] + 1[2][2] + ... + 1[2][j]+
          a[3][1] +   ...   + ... + a[3][j]+
             +                         +
            ....                      ....
             +                         + 
          a[i][1] +   ...   + ... + a[i][j]

作用

主要作用是可以在是可以在O(1)情況下求出任何子矩陣的和

圖解:

image

在這個矩陣(二維數組)中,我們要求上圖中紫色區域的和,現在我們已經預處理出了所有點的首碼和,現在給定兩個點\((x1,y1)\)\((x2,y2)\),我們需要求的是以這兩個點連線為對角線的一個子矩陣的數值之和。首先我們可以把\(s[x2][y2]\)求出來,它代表整個大矩形的首碼和,然後我們分別減去它右邊多出來的一塊的首碼和和上邊多出來一塊的首碼和,但是需要註意下邊的左上角被減了兩次,所以我們需要加回來一次。故對於一次的查詢是\(s[i][j]\)應該等於\(s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]\)

  • 所求子矩陣和=\(s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]\);

方法

二維數組求首碼和方法

const int N = 10010;
int a[N][N],s[N][N]
//n,m為鍵盤輸入
for(int i = 1; i <= n; i++)
{
    for(int j = 1;j <= m; j++)
    {
       scanf("%d",&a[i][j]);
    }
}
for(int i = 1; i<= n; i++)
{
    for(int j = 1; j <= m; j++)
    {
       s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
    }
}

具體代碼!!!

#include <iostream>
 
const int N = 1010;
int n,m,q;
int a[N][N],s[N][N];
 
int main()
{
    scanf("%d%d%d",&n,&m,&q);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1;j <= m; j++)
        {
            scanf("%d",&a[i][j]);
        }
    }
    for(int i = 1; i<= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];
        }
    }
    while(q--)
    {
        int x1,y1,x2,y2,re;
        scanf("%d%d%d%d",&x1,&y2,&x2,&y2);
        re = s[x2][y2] - s[x1-1][y2] - s[x2][y1-1] + s[x1-1][y1-1];
        printf("%d\n",re);
    }
}

本文來自小默的博客,轉載請註明原文鏈接:https://www.cnblogs.com/momotrace/p/Prefix-sum.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 這幾周與公司的軟體開發專家(職稱)討論產品的軟體新架構與方案,主要涉及兩點 是否復用現有的核心機制 基於領域建模設計 關於第一點,雙方達成一致。 關於第二點,領域可以理解為業務,業務專家(產品經理,需求工程師,臨床工程師等)與研發人員一起,通過頭腦風暴、事件風暴、會議、協作等方式,使得研發人員對產品 ...
  • LOD:迪米特法則(Law of Demeter) CRP:合成復用原則(Composite Reuse Principle) DRY:不要重覆你自己原則 (Don’t Repeat Yourself Principle) KISS:KISS原則 (Keep It Simple and Stupid ...
  • move : 移動語義,得到右值類型 forward:類型轉發,能夠識別左值和右值類型 只有兩種形式的引用,左值引用和右值引用,萬能引用不是一種引用類型,它存在於模板的引用摺疊情況,但是能夠接受左值和右值 區分左值和右值得一個簡單方式就是能不能取地址 一個右值一旦有名字那麼就變成了左值 #inclu ...
  • 術語表 第一章 FizzBuzz 用來編程面試中篩選候選者的測試。 操作系統 扮演電腦物理組件與人之間的中間人的一個程式。 圖形用戶界面(GUI) 操作系統的一部分,用戶在屏幕上看到的內容。 開源 軟體不歸某個公司或個人所有,而是由一群志願者維護。 Windows 微軟推出的操作系統。 UNIX ...
  • 一個典型的單線程伺服器示例如下: while (true) { Socket socket = null; try { // 接收客戶連接 socket = serverSocket.accept(); // 從socket中獲得輸入流與輸出流,與客戶通信 ... } catch(IOExcepti ...
  • java面向對象三大特征即為:繼承封裝多態。而多態需要三大必要條件。分別是:繼承、方法重寫、父類引用指向子類對象。我們先一個一個來理解。 1、首先是繼承和重寫。這個很簡單。因為多態就是建立在不同的重寫之上的。也就是說多態就是在使用著一個方法的不同重寫。而重寫又是依賴著繼承關係。 2、這個父類引用指向 ...
  • 一:背景 1. 講故事 今天是五一的最後一天,想著長期都在 Windows 平臺上做開發,準備今天換到 Ubuntu 系統上體驗下,主要是想學習下 AT&T 風格的彙編,這裡 Visual Studio 肯定是裝不了了,還得上 VSCode,剛好前幾天買了一個小工控機,這裡簡單記錄下 零到一 的過程 ...
  • 方法重載 同一個類中,多個方法的名稱相同,但是形參列表不同。 方法重載的形式 同一個類中,方法名稱相同、形參列表不同 形參的個數、類型、順序不同 形參的名稱無關 方法重載的調用流程 當程式調用一個重載方法時,編譯器會根據參數列表的不同自動匹配最合適的方法,這種機制叫做方法重載的“重載解析”。 根據方 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...