線段樹講解(小進階)

目錄

前言

一、線段樹知識回顧

線段樹區間加減

區間修改維護:

區間修改的操作:

區間修改update:

線段樹的區間查詢

區間查詢:

區間查詢的操作:

遞歸查詢過程:

區間查詢query:

代碼:

二、線段樹的區間修改---乘上一個數’x'

build

區間修改

update

mulpr_update

push_up

代碼:

push_down

左:

右:

代碼:

區間查詢query

代碼:

三、例題

例題:P3373 【模板】線段樹 2 - 洛谷

?編輯

完整代碼:

總結


前言

本篇文章主要是根據P3373 【模板】線段樹 2 - 洛谷對線段樹進行進一步的講解,因為比較笨拙加上畫圖耗時大,沒有圖文搭配講解,只有純粹的文字講解,但是也是非常清楚的,很容易就能理解


一、線段樹知識回顧

我們在進一步學習前,先來看一下前置知識

開一個build函數建樹,具體操作如下:

1.定義數組:首先,需要定義一個大小為 4n 的數組,其中 n 是線段樹的葉子節點數量。這個數組將用于存儲線段樹的節點信息。

2.構建線段樹:一般將線段樹按照完全二叉樹的形式存儲在數組中。假設根節點在數組中的索引是 1,那么對于節點 i,其左子節點為 2i,右子節點為 2i + 1。

3.存儲節點信息:每個節點需要保存代表的區間范圍和相應的信息,比如區間的最大值、最小值、和等等。在數組中,可以按照某種順序依次存儲這些信息,以便后續的查詢和更新操作。

4.建立線段樹:通過遞歸或迭代的方式構建線段樹。一般會從葉子節點開始向上構建,通過合并子節點的信息得到父節點的信息,直至構建完整的線段樹。

5.查詢和更新:通過線段樹的結構和數組存儲,可以實現高效的區間查詢和更新操作。比如,對于查詢一個區間的最大值,可以通過遞歸向下查詢到包含目標區間的節點,并根據存儲的信息計算出結果。

6.記得注意邊界情況:在實現線段樹時,需要考慮樹的邊界情況,比如樹的根節點索引是 1,葉子節點索引從 n+1 開始等,以確保正確地訪問和操作節點。

// 建樹函數
void build(LL l, LL r, LL fa) {if (l == r) { // 如果區間只有一個元素t[fa] = a[l] % m; // 直接賦值return;}LL mid = (l + r) >> 1; // 計算中間節點build(l, mid, fa << 1); // 遞歸構建左子樹build(mid + 1, r, fa << 1 | 1); // 遞歸構建右子樹push_up(fa); // 更新父節點
}

線段樹區間加減

區間修改維護:

1.需要修改線段樹中某個特定區間的值時,可以通過遞歸的方式向下更新區間。
2.如果要修改的區間與當前節點表示的區間沒有交集,則無需修改該節點。
3.如果要修改的區間完全包含當前節點的區間,則直接更新當前節點的信息,并將修改操作下傳給子節點。
4.如果要修改的區間與當前節點的區間部分相交,則需要先將當前節點的信息更新,然后將修改操作同時下傳給左右子節點。


區間修改的操作:


1.區間修改的操作通常包括加法、減法、賦值等。
2.當需要對區間內的每個元素進行相同的修改時,可以利用線段樹的特性進行高效操作。
3.在修改區間時,需要根據當前節點的區間范圍、待修改區間和修改方式來確定如何操作當前節點和其子節點。


遞歸更新過程:


從線段樹的根節點開始遞歸向下更新,直到找到包含待修改區間的葉子節點。
在遞歸過程中根據節點的區間范圍和待修改區間的關系,決定如何更新節點的信息并向下傳遞修改操作。
? ? ? ?此外,對于區間操作,我們考慮引入一個名叫“ lazy tag ”(懶標記)的東西——之所以稱其“lazy”,是因為原本區間修改需要通過先改變葉子節點的值,然后不斷地向上遞歸修改祖先節點直至到達根節點,時間復雜度最高可以到達 O(nlogn) 的級別。但當我們引入了懶標記之后,區間更新的期望復雜度就降到了 O(logn) 的級別且甚至會更低。

因此,我們再弄一個tag數組,大小也是4*N

區間修改update:

void psuh_up(LL fa) {t[fa] = t[fa << 1] + t[fa << 1 | 1];//向上不斷維護父節點
}
void push_down(LL l,LL r,LL fa) {LL mid = (l + r) >> 1;t[fa << 1] += tag[fa] * (mid - l + 1);tag[fa << 1] += tag[fa];t[fa << 1|1] += tag[fa] * (r-mid);tag[fa << 1|1] += tag[fa];tag[fa] = 0;// //每次將懶惰標識下放到兩個兒子節點,自身置為0,以此不斷向下傳遞 
}
void update(LL ql, LL qr, LL l, LL r, LL k, LL fa) {if (ql <= l && qr >= r) //如果區間被包含,直接返回該節點的懶惰標識{t[fa] +=k * (r - l + 1);tag[fa] += k;return;}LL mid = (l + r) >> 1;push_down(l, r, fa);//下放懶惰標識if (ql <= mid)update(ql, qr, l, mid,k, fa << 1);//朝左邊下放if (qr > mid)update(ql, qr, mid + 1, r,k, fa << 1 | 1);//右邊psuh_up(fa);//再將修改后的值向上返回,維護父節點
}

我們這一期會對update和push_down進行更改

線段樹的區間查詢

  1. 區間查詢

    • 當需要查詢線段樹中某個特定區間的信息時,可以通過遞歸的方式向下查詢區間。
    • 如果要查詢的區間與當前節點表示的區間沒有交集,則無需查詢該節點,直接返回默認值(如0或無窮大)。
    • 如果要查詢的區間完全包含當前節點的區間,則直接返回該節點存儲的信息。
    • 如果要查詢的區間與當前節點的區間部分相交,則需要同時查詢左右子節點,并根據查詢結果合并得到最終結果。
  2. 區間查詢的操作

    • 區間查詢的操作通常包括求和、求最大值、求最小值等。
    • 在查詢區間時,需要根據當前節點的區間范圍、待查詢區間和查詢方式來確定如何操作當前節點和其子節點。
  3. 遞歸查詢過程

    • 從線段樹的根節點開始遞歸向下查詢,直到找到包含待查詢區間的葉子節點。
    • 在遞歸過程中根據節點的區間范圍和待查詢區間的關系,決定如何查詢節點的信息并向下傳遞查詢操作。
    • 最終將所有查詢結果合并得到最終的區間查詢結果。

? ? ? 通過以上方法,可以實現對線段樹中特定區間的查詢操作。線段樹區間查詢是線段樹的一個重要功能,能夠快速有效地獲取區間內的信息,提高了區間查詢的效率。

區間查詢query:

LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0;if (ql <= l && qr >= r) 如果區間被包含,直接返回該節點的懶惰標識{return t[fa];}LL mid = (l + r) >> 1;push_down(l, r, fa);//沒有被包含,下放任務if (ql <= mid)ret += query(ql, qr, l, mid, fa << 1);if (qr > mid)ret += query(ql, qr, mid + 1, r, fa << 1|1);//在查詢范圍的左區間和右區間的值相加并返回return ret;
}

代碼:

#include<iostream>
using namespace std;
const int N = 1e5 + 10;
typedef long long LL;
LL n, m, t[N * 4], tag[N * 4], a[N];
void psuh_up(LL fa) {t[fa] = t[fa << 1] + t[fa << 1 | 1];//向上不斷維護父節點
}
void push_down(LL l,LL r,LL fa) {LL mid = (l + r) >> 1;t[fa << 1] += tag[fa] * (mid - l + 1);tag[fa << 1] += tag[fa];t[fa << 1|1] += tag[fa] * (r-mid);tag[fa << 1|1] += tag[fa];tag[fa] = 0;// //每次將懶惰標識下放到兩個兒子節點,自身置為0,以此不斷向下傳遞 
}
LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0;if (ql <= l && qr >= r) 如果區間被包含,直接返回該節點的懶惰標識{return t[fa];}LL mid = (l + r) >> 1;push_down(l, r, fa);//沒有被包含,下放任務if (ql <= mid)ret += query(ql, qr, l, mid, fa << 1);if (qr > mid)ret += query(ql, qr, mid + 1, r, fa << 1|1);//在查詢范圍的左區間和右區間的值相加并返回return ret;
}
void update(LL ql, LL qr, LL l, LL r, LL k, LL fa) {if (ql <= l && qr >= r) //如果區間被包含,更新懶惰標識并返回{t[fa] +=k * (r - l + 1);tag[fa] += k;return;}LL mid = (l + r) >> 1;push_down(l, r, fa);//下放懶惰標識if (ql <= mid)update(ql, qr, l, mid,k, fa << 1);//朝左邊下放if (qr > mid)update(ql, qr, mid + 1, r,k, fa << 1 | 1);//右邊psuh_up(fa);//再將修改后的值向上返回,維護父節點
}
void build(LL l, LL r, LL fa) {if (l == r) // //如果左右區間相同,那么必然是葉子節,只有葉子節點是被真實賦值的{t[fa] = a[l];return;}LL mid = (l + r) >> 1;build(l, mid, fa << 1);build(mid + 1, r, fa << 1 | 1);//使用二分來優化psuh_up(fa);//此處由于我們是要通過子節點來維護父節點,所以push_up的位置應當是在回溯時將子節點的值取和交給父節點
}
int main() {cin >> n >> m;for (int i = 1; i <= n; i++)cin >> a[i];build(1, n, 1);while (m--) {int op; cin >> op;if (op == 1) {LL x, y, k; cin >> x >> y >> k;update(x, y, 1, n, k, 1);}else if(op==2){LL x, y;cin >> x >> y;cout << query(x, y, 1, n, 1) << endl;}}return 0;
}

二、線段樹的區間修改---乘上一個數’x'

老樣子,先看題目

根據題目意思先建樹

build:

代碼:

// 建樹函數
void build(LL l, LL r, LL fa) {if (l == r) { // 如果區間只有一個元素t[fa] = a[l] % m; // 直接賦值return;}LL mid = (l + r) >> 1; // 計算中間節點build(l, mid, fa << 1); // 遞歸構建左子樹build(mid + 1, r, fa << 1 | 1); // 遞歸構建右子樹push_up(fa); // 更新父節點
}

因為題目增加了一個區間乘一個數,所以我們需要維護兩個tag數組,tag1,tag2,大小都是n*4;

令tag1為區間乘一個數的數組,由于區間乘一個數,所以數組tag1全部初始化為1;

代碼:

int main() {cin >> n >>q>> m;for (int i = 0; i <= N * 4; i++)tag1[i] = 1;for (int i = 1; i <= n; i++)cin >> a[i];build(1, n, 1);while (q--) {int op; cin >> op;if (op == 2) {LL x, y, k; cin >> x >> y >> k;update(x, y, 1, n, 1, k%m);}else if (op == 3) {LL x, y; cin >> x >> y;cout << query(x, y, 1, n, 1)%m  << endl;}else if (op == 1) {LL x, y, k; cin >> x >> y >> k;mulpr_update(x, y, 1, n, 1, k);}}return 0;
}

這個模去m是題目要求的,后面不會去詳細講,只會說tag數組如何維護以及query的一點改動;

區間修改

需要兩個不同的update來維護區間加和區間乘

區間加就不多贅述了

update

// 更新函數
void update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新區間完全覆蓋當前區間t[fa] = (t[fa] + (r - l + 1) * k) % m; // 更新當前節點的值tag2[fa] = (tag2[fa] + k) % m; // 更新加法標記return;}LL mid = (l + r) >> 1; // 計算中間節點push_down(l, r, fa); // 向下更新標記if (ql <= mid) // 如果更新區間在左子樹update(ql, qr, l, mid, fa << 1, k); // 更新左子樹if (qr > mid) // 如果更新區間在右子樹update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子樹push_up(fa); // 更新父節點
}

來看一下區間乘

如果要更新的區間覆蓋了當前的區間,直接更新當前t數組的值,更新tag1,tag2的懶惰標識,然后return,就不需要下放懶惰標識了;

如果區間沒有覆蓋,puah_down下放懶惰標識,更新左邊,然后更新右邊,然后push_up向上更新父節點;

mulpr_update


// 乘法更新函數
void mulpr_update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新區間完全覆蓋當前區間t[fa] = t[fa] * k % m; // 更新當前節點的值tag1[fa] = tag1[fa] * k % m; // 更新乘法標記tag2[fa] = tag2[fa] * k % m; // 更新加法標記return;}LL mid = (l + r) >> 1; // 計算中間節點push_down(l, r, fa); // 向下更新標記if (ql <= mid) // 如果更新區間在左子樹mulpr_update(ql, qr, l, mid, fa << 1, k); // 更新左子樹if (qr > mid) // 如果更新區間在右子樹mulpr_update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子樹push_up(fa); // 更新父節點
}

push_up

代碼:

// 向上更新函數,更新父節點的值
void push_up(LL fa) {// 父節點的值等于左右子節點的和,取模 mt[fa] = (t[fa << 1] + t[fa << 1 | 1]) % m;
}

push_down

比較有難度的一個push_down,如果思路清晰的話就會變得很簡單

左:

先將需要下放懶惰標識的區間取mid,更新樹t左子節點,用tag1和tag2 fa位置的懶惰值更新

然后更新tag1左子節點,因為是乘,所以將tag1fa父節點的懶惰標識乘上tag1[fa<<1]左子節點的懶惰標識更新該左子節點的懶惰標識

然后更新tag2左子節點,雖然是區間加的懶惰數組,但是tag1和tag2作用在同一個線段樹,所以在更新tag2時需要看看tag1[fa]有沒有懶惰標識,有的話得加上tag1[fa] * tag2[fa << 1],即如果tag1有懶惰標識,將其乘上tag2左子節點[fa<<1]原本有的懶惰標識;

右:

更新樹t右子節點,用tag1和tag2 fa位置的懶惰值更新

然后更新tag1右子節點,因為是乘,所以將tag1fa父節點的懶惰標識乘上tag1[fa<<1|1]右子節點的懶惰標識更新該左子節點的懶惰標識

然后更新tag2右子節點,雖然是區間加的懶惰數組,但是tag1和tag2作用在同一個線段樹,所以在更新tag2時需要看看tag1[fa]有沒有懶惰標識,有的話得加上tag1[fa] * tag2[fa << 1|1],即如果tag1有懶惰標識,將其乘上tag2左子節點[fa<<1|1]原本有的懶惰標識;

代碼:

// 向下更新函數,處理懶惰標記
void push_down(LL l, LL r, LL fa) {LL mid = (l + r) >> 1; // 計算中間節點// 更新左子節點t[fa << 1] = (tag1[fa] * t[fa << 1] % m + tag2[fa] * (mid - l + 1) % m) % m;tag1[fa << 1] = (tag1[fa << 1] * tag1[fa]) % m; // 更新乘法標記tag2[fa << 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1] % m) % m; // 更新加法標記// 更新右子節點t[fa << 1 | 1] = (tag1[fa] * t[fa << 1 | 1] % m + (tag2[fa] * (r - mid)) % m) % m;tag1[fa << 1 | 1] = (tag1[fa << 1 | 1] * tag1[fa]) % m; // 更新乘法標記tag2[fa << 1 | 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1 | 1] % m) % m; // 更新加法標記// 清空當前節點的標記tag1[fa] = 1;tag2[fa] = 0;
}

區間查詢query

代碼:

// 查詢函數
LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0; // 初始化返回值if (ql <= l && qr >= r) { // 如果查詢區間完全覆蓋當前區間return t[fa] % m; // 返回當前節點的值}LL mid = (l + r) >> 1; // 計算中間節點push_down(l, r, fa); // 向下更新標記if (ql <= mid) // 如果查詢區間在左子樹ret = (ret + query(ql, qr, l, mid, fa << 1)) % m; // 查詢左子樹if (qr > mid) // 如果查詢區間在右子樹ret = (ret + query(ql, qr, mid + 1, r, fa << 1 | 1)) % m; // 查詢右子樹return ret % m; // 返回結果
}

三、例題

例題:P3373 【模板】線段樹 2 - 洛谷

完整代碼:


#include <iostream>
#include <cstring>
using namespace std;// 定義常量 N,表示數組的最大大小
const int N = 1e5 + 10;// 定義長整型別名 LL
typedef long long LL;// 全局變量
LL n, m, q; // n: 數組大小, m: 模數, q: 查詢次數
LL t[N * 4], a[N]; // t: 線段樹數組, a: 原始數組
LL tag1[N * 4], tag2[N * 4]; // tag1: 乘法標記, tag2: 加法標記// 向上更新函數,更新父節點的值
void push_up(LL fa) {// 父節點的值等于左右子節點的和,取模 mt[fa] = (t[fa << 1] + t[fa << 1 | 1]) % m;
}// 向下更新函數,處理懶惰標記
void push_down(LL l, LL r, LL fa) {LL mid = (l + r) >> 1; // 計算中間節點// 更新左子節點t[fa << 1] = (tag1[fa] * t[fa << 1] % m + tag2[fa] * (mid - l + 1) % m) % m;tag1[fa << 1] = (tag1[fa << 1] * tag1[fa]) % m; // 更新乘法標記tag2[fa << 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1] % m) % m; // 更新加法標記// 更新右子節點t[fa << 1 | 1] = (tag1[fa] * t[fa << 1 | 1] % m + (tag2[fa] * (r - mid)) % m) % m;tag1[fa << 1 | 1] = (tag1[fa << 1 | 1] * tag1[fa]) % m; // 更新乘法標記tag2[fa << 1 | 1] = (tag2[fa] + tag1[fa] * tag2[fa << 1 | 1] % m) % m; // 更新加法標記// 清空當前節點的標記tag1[fa] = 1; tag2[fa] = 0;
}// 建樹函數
void build(LL l, LL r, LL fa) {if (l == r) { // 如果區間只有一個元素t[fa] = a[l] % m; // 直接賦值return;}LL mid = (l + r) >> 1; // 計算中間節點build(l, mid, fa << 1); // 遞歸構建左子樹build(mid + 1, r, fa << 1 | 1); // 遞歸構建右子樹push_up(fa); // 更新父節點
}// 查詢函數
LL query(LL ql, LL qr, LL l, LL r, LL fa) {LL ret = 0; // 初始化返回值if (ql <= l && qr >= r) { // 如果查詢區間完全覆蓋當前區間return t[fa] % m; // 返回當前節點的值}LL mid = (l + r) >> 1; // 計算中間節點push_down(l, r, fa); // 向下更新標記if (ql <= mid) // 如果查詢區間在左子樹ret = (ret + query(ql, qr, l, mid, fa << 1)) % m; // 查詢左子樹if (qr > mid) // 如果查詢區間在右子樹ret = (ret + query(ql, qr, mid + 1, r, fa << 1 | 1)) % m; // 查詢右子樹return ret % m; // 返回結果
}// 更新函數
void update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新區間完全覆蓋當前區間t[fa] = (t[fa] + (r - l + 1) * k) % m; // 更新當前節點的值tag2[fa] = (tag2[fa] + k) % m; // 更新加法標記return;}LL mid = (l + r) >> 1; // 計算中間節點push_down(l, r, fa); // 向下更新標記if (ql <= mid) // 如果更新區間在左子樹update(ql, qr, l, mid, fa << 1, k); // 更新左子樹if (qr > mid) // 如果更新區間在右子樹update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子樹push_up(fa); // 更新父節點
}// 乘法更新函數
void mulpr_update(LL ql, LL qr, LL l, LL r, LL fa, LL k) {if (ql <= l && qr >= r) { // 如果更新區間完全覆蓋當前區間t[fa] = t[fa] * k % m; // 更新當前節點的值tag1[fa] = tag1[fa] * k % m; // 更新乘法標記tag2[fa] = tag2[fa] * k % m; // 更新加法標記return;}LL mid = (l + r) >> 1; // 計算中間節點push_down(l, r, fa); // 向下更新標記if (ql <= mid) // 如果更新區間在左子樹mulpr_update(ql, qr, l, mid, fa << 1, k); // 更新左子樹if (qr > mid) // 如果更新區間在右子樹mulpr_update(ql, qr, mid + 1, r, fa << 1 | 1, k); // 更新右子樹push_up(fa); // 更新父節點
}// 主函數
int main() {cin >> n >> q >> m; // 輸入數組大小 n, 查詢次數 q, 模數 mfor (int i = 0; i <= N * 4; i++) tag1[i] = 1; // 初始化乘法標記為 1for (int i = 1; i <= n; i++) cin >> a[i]; // 輸入數組元素build(1, n, 1); // 構建線段樹while (q--) { // 處理每個查詢int op; cin >> op; // 輸入操作類型if (op == 2) { // 加法更新操作LL x, y, k; cin >> x >> y >> k; // 輸入區間 [x, y] 和加數 kupdate(x, y, 1, n, 1, k % m); // 執行加法更新}else if (op == 3) { // 查詢操作LL x, y; cin >> x >> y; // 輸入查詢區間 [x, y]cout << query(x, y, 1, n, 1) % m << endl; // 輸出查詢結果}else if (op == 1) { // 乘法更新操作LL x, y, k; cin >> x >> y >> k; // 輸入區間 [x, y] 和乘數 kmulpr_update(x, y, 1, n, 1, k); // 執行乘法更新}}return 0; // 程序結束
}


總結

本期關于線段樹的講解就到這里,有什么疑問或者有什么錯誤的地方歡迎大家一起交流學習,下期帶來線段樹的離散化,二分搜索等進階內容

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/80149.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/80149.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/80149.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

neo4j中節點內的名稱顯示不全解決辦法(如何讓label在節點上自動換行)

因為節點過多而且想讓節點中所有文字都顯示出來而放大節點尺寸 從neo4j中導出png,再轉成PDF來查看時&#xff0c;要看清節點里面的文字就得放大5倍才行 在網上看了很多讓里面文字換行的辦法都不行 然后找到一個比較靠譜的辦法是在要顯示的標簽內加換行符 但是我的節點上顯示的是…

SQL進階知識:五、存儲過程和函數

今天介紹下關于存儲過程和函數的詳細介紹&#xff0c;并結合MySQL數據庫提供實際例子。 在MySQL中&#xff0c;存儲過程&#xff08;Stored Procedures&#xff09;和函數&#xff08;Functions&#xff09;是數據庫編程的重要組成部分&#xff0c;它們可以封裝SQL語句&#xf…

CONDA:用于 Co-Salient 目標檢測的壓縮深度關聯學習(總結)

摘要 一 介紹 二 有關工作 三 提出的方法 圖2&#xff1a;我們的凝聚式深度關聯&#xff08;CONDA&#xff09;模型的整體流程圖。具體來說&#xff0c;凝聚式深度關聯&#xff08;CONDA&#xff09;模型首先利用圖像特征來計算超關聯。然后&#xff0c;全像素超關聯由對應誘…

node.js 實戰——(path模塊 知識點學習)

path 模塊 提供了操作路徑的功能 說明path. resolve拼接規范的絕對路徑path. sep獲取操作系統的路徑分隔符path. parse解析路徑并返回對象path. basename獲取路徑的基礎名稱path. dirname獲取路徑的目錄名path. extname獲得路徑的擴展名 resolve 拼接規范的絕對路徑 const…

Kimi做內容社區,劍指小紅書?

原創科技新知AI新科技組作者丨櫻木編輯丨江蘺 主編丨九黎 對于當前融資形勢并不明朗的大模型六小龍來說&#xff0c;該如何生存下去&#xff0c;似乎成了各家急需解決的問題。 根據PitchBook數據&#xff0c;今年一季度風險投資機構在中國AI領域共完成144筆交易&#xff0c;投…

opencv--圖像濾波

圖像濾波 含義 方法 噪聲是怎么產生的 線性濾波 概念 利用窗口對圖像中的像素進行加權求和的濾波方式。 圖像來源于小虎教程。 圖像的濾波是二維濾波的過程。 濾波器窗口&#xff1a; 濾波器窗口&#xff08;也稱為卷積核或模板&#xff09;是一個小的矩陣&#xff08;通常為…

Java 實現SpringContextUtils工具類,手動獲取Bean

SpringContextUtils 工具類實現 下面是一個完整的 Spring 上下文工具類實現&#xff0c;用于從 Spring 容器中獲取 Bean。這個工具類考慮了線程安全、性能優化和易用性&#xff0c;并提供了多種獲取 Bean 的方式。 完整實現代碼 import org.springframework.beans.BeansExce…

基于 Vue 2 開發的分頁卡片列表組件(帶懶加載和點擊事件)

功能目標&#xff1a; CardList.vue 中支持分頁&#xff0c;每頁顯示指定數量的卡片。添加“加載中”動畫。支持懶加載&#xff1a;滾動到底部自動加載下一頁。點擊卡片的事件邏輯由 Card.vue 內部發出&#xff0c;并由 CardList 向上傳遞。 主頁面文件 Home.vue <templat…

【數據結構和算法】6. 哈希表

本文根據 數據結構和算法入門 視頻記錄 文章目錄 1. 哈希表的概念1.1 哈希表的實現方式1.2 哈希函數&#xff08;Hash Function&#xff09;1.3 哈希表支持的操作 2. Java實現 在前幾章的學習中&#xff0c;我們已經了解了數組和鏈表的基本特性&#xff0c;不管是數組還是鏈表…

【python】如何將文件夾及其子文件夾下的所有word文件匯總導出到一個excel文件里?

根據你的需求,這里提供一套完整的Python解決方案,支持遞歸遍歷子文件夾、提取Word文檔內容(段落+表格),并整合到Excel中。以下是代碼實現及詳細說明: 一個單元格一個word的全部內容 完整代碼 # -*- coding: utf-8 -*- import os from docx import Document import pand…

leetcode-位運算

位運算 371. 兩整數之和 題目 給你兩個整數 a 和 b &#xff0c;不使用 運算符 和 - &#xff0c;計算并返回兩整數之和。 示例 1&#xff1a; 輸入&#xff1a; a 1, b 2 輸出&#xff1a; 3 示例 2&#xff1a; 輸入&#xff1a; a 2, b 3 輸出&#xff1a; 5 提示&am…

飛帆控件:在編輯模式下額外加載的庫

飛帆是一個自由的控件設計平臺。在飛帆中&#xff0c;我們可以很方便地創建基于 Vue 2 組件的控件&#xff0c;并使用控件來搭建網頁。 他山之石&#xff0c;可以攻玉。在創建控件中&#xff0c;使用 js 、css 依賴庫能讓我們的控件更強大。 有些時候&#xff0c;在編輯模式下…

GPLT-2025年第十屆團體程序設計天梯賽總決賽題解(共計266分)

今天偶然發現天梯賽的代碼還保存著&#xff0c;于是決定寫下這篇題解&#xff0c;也算是復盤一下了 L1本來是打算寫的穩妥點&#xff0c;最后在L1-6又想省時間&#xff0c;又忘記了insert&#xff0c;replace這些方法怎么用&#xff0c;也不想花時間寫一個文件測試&#xff0c…

編碼轉換器

大批量轉換編碼 可以將整個工程文件夾從GB18030轉為UTF-8 使用Qt C制作 項目背景 比較老的工程&#xff0c;尤其是keil嵌入式的工程&#xff0c;其文本文件&#xff08;.c、.cpp、.h、.txt、……&#xff09;編碼為gb2312&#xff0c;這為移植維護等帶來了不便。現在uit-8用…

STL 核心模塊

很好&#xff01;你想深入 STL&#xff08;Standard Template Library&#xff09;和容器算法&#xff0c;是學習 C 非常關鍵的一步。下面我給你整理一份STL 容器 算法的入門指南&#xff0c;適合從零起步掌握這部分內容。 &#x1f31f; 一、STL 核心模塊 STL 分為三大塊&am…

2024沈陽區域賽,D - Dot Product Game

題目鏈接 樹狀數組求逆序對 #include<bits/stdc.h> using namespace std; using lllong long; typedef pair<int,int>PII; typedef priority_queue<int> upq; typedef priority_queue<int,vector<int>,greater<int>> dpq; const int M99…

簡易博客點贊系統實現

簡易博客點贊系統 好久沒寫 Java 了&#xff0c;整個簡單的項目進行康復訓練。 基于 Spring Boot SSM MySQL Mybatis-Plus Knife4j Swagger 的一個簡易博客點贊系統 開源地址&#xff1a;https://github.com/FangMoyu/simple-thumb 功能 登錄獲取當前登錄用戶獲取博客…

一個既簡單又詭異的問題

public class DaYaoGuai {static String s;public static void main(String[] args) {Thread t1 new Thread(){Overridepublic void run() {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}s"深圳";}};t1.start();Thre…

使用docker在manjaro linux系統上運行windows和ubuntu

因為最近項目必須要使用指定版本的solidworks和maxwell&#xff08;都只能在win系統上使用&#xff09;, 且目前的ubuntu容器是沒有桌面的&#xff0c;導致我運行不了一些帶圖形的ros2功能。無奈之下&#xff0c;決定使用docker-compose寫一下配置文件&#xff0c;徹底解決問題…

Elasticsearch中的_source字段講解

_source 在 Elasticsearch 查詢中用于限制返回的字段,類似于 SQL 中的 SELECT 指定列。 代碼示例: esSearchResults = es_service.search_documents({"query": {"terms": {"file_id":