跳到主要内容敌情监控:多语言实现区间连续 K 个营地最小兵力之和 | 极客日志编程语言java算法
敌情监控:多语言实现区间连续 K 个营地最小兵力之和
一个敌情监控问题,要求在动态变化的 N 个营地中,快速查询任意区间内连续 K 个营地的最小兵力之和。支持单点增加或减少兵力的操作。文章提供了基于线段树的解决方案,维护区间和与长度为 K 的子区间最小和,并给出了 Java、Python、C++、JavaScript 和 C 五种语言的完整实现代码。
深海蔚蓝60 浏览 敌情监控:多语言实现区间连续 K 个营地最小兵力之和
题目描述
H 国最近在和 M 国打仗,H 国间谍头子 Peter 负责监视敌国 M 的兵力部署情况。M 国沿边境线布置了 N 个营地,Peter 的任务就是监视这些营地的兵力部署情况。中央情报局要研究敌情,所以 Peter 要汇报一段兵营中哪个连续的 K 个营地驻兵最少之和是多少,可以作为攻击的突破点。
例如:'Peter,快汇报第 2 个营地到第 10 个营地中 H 连续的 3 座兵营人数之和最少';而且每个营地的人数在不断变化。请你帮 Peter 设计一个程序,快速计算汇到的结果。
输入描述
第一行 3 个正整数:N K L
N(N<=50000),表示敌人营地兵营的数量,每个营地编号为 1,2,3...N.K 表示连续的兵营数,L 表示后续要问的命令数量;接下来有 N 个正整数,第 i 个正整数 ai 代表第 i 个营地里开始时有 ai 个人(1<=ai<=50000)
接下来有行有 L 条命令。命令有 3 种形式:
(1)Add i j, i 和 j 为正整数,表示第 i 个营地增加 j 个人(j 不超过 30)
(2)Sub i j, i 和 j 为正整数,表示第 i 个营地减少 j 个人(j 不超过 30)
(3)Query i j, i 和 j 为正整数,i<=j,表示询问问第 i 个营地到第 j 个营地,连续 H 个兵营人数之和最少的总人数
其中:j-i+1>=K,每组数据最多有 50 条命令
输出描述
对于每个 Query 询问,输出一个整数并回车,表示询问的该段中的连续的 K 座兵营人数之和最少的数量,这个数保持在 int 以内
示例
说明 第一行第一个正整数 5,表示敌人有 5 个营地,第二个正整数 2,表示连续营地的数量是 2,第 3 个正整数 3,表示后续会有 3 条询问的命令;接下来一行有 5 个正整数,分别表示每个营地里开始的人数,第 1 个营地开始有 1 个人,第 2 个营地开始有 2 个人,第 3 个营地开始有 2 个人,第 4 个营地开始有 3 个人,第 5 个营地开始有 3 个人;
接下来每行有一条命令:
第 1 条命令:Query 1 3 表示要查询第 1 到第 3 个营地的总人数,结果:1+2=3 第一个输出是:3
第 2 条命令:Add 3 6 表示第 3 个营地增加 6 个人 无需输出
第 3 条命令:Query 2 4 表示查询第 2 到第 4 个营地的总人数,结果:2+8=10 第一个输出是:10,注意这里第 3 个营地人数在第 2 条命令中增加了 6
思路分析
- 问题核心:对于每个 Query,需要在区间 [i, j] 内找到所有长度为 K 的子区间,求它们和的最小值
- 数据规模:
- N ≤ 50000
- 最多 50 条命令(L ≤ 50)
- 单点更新,j ≤ 30(变化不大)
- 关键点:
- 需要快速查询区间内固定长度子数组的最小和
- 由于命令数很少,可以用线段树维护区间信息
- 每个节点需要存储的信息:区间和、区间内所有长度为 K 的子区间的最小和
Java 实现
import java.io.*;
public class Main {
static class SegmentTree {
int n, k;
int[] sum;
int[] minKSum;
SegmentTree( n, k, [] arr) {
.n = n;
.k = k;
sum = [ * n];
minKSum = [ * n];
build(, , n, arr);
}
{
(l == r) {
sum[node] = arr[l];
minKSum[node] = (k == ) ? arr[l] : Integer.MAX_VALUE;
;
}
(l + r) / ;
build(node * , l, mid, arr);
build(node * + , mid + , r, arr);
sum[node] = sum[node * ] + sum[node * + ];
(r - l + >= k) {
minKSum[node] = Math.min(minKSum[node * ], minKSum[node * + ]);
(mid - l + >= k - (r - mid)) {
Math.max(l, mid - k + );
( leftStart; start <= mid && start + k - <= r; start++) {
start + k - ;
(end <= r) {
minKSum[node] = Math.min(minKSum[node], querySum(start, end));
}
}
}
} {
minKSum[node] = Integer.MAX_VALUE;
}
}
{
(l == r) {
sum[node] += delta;
(k == ) {
minKSum[node] = sum[node];
}
;
}
(l + r) / ;
(idx <= mid) {
update(node * , l, mid, idx, delta);
} {
update(node * + , mid + , r, idx, delta);
}
sum[node] = sum[node * ] + sum[node * + ];
(r - l + >= k) {
minKSum[node] = Math.min(minKSum[node * ], minKSum[node * + ]);
(mid - l + >= k - (r - mid)) {
Math.max(l, mid - k + );
( leftStart; start <= mid && start + k - <= r; start++) {
start + k - ;
(end <= r) {
minKSum[node] = Math.min(minKSum[node], querySum(start, end));
}
}
}
} {
minKSum[node] = Integer.MAX_VALUE;
}
}
{
(ql > qr || r - l + < k) {
Integer.MAX_VALUE;
}
(ql <= l && r <= qr) {
(r - l + >= k) {
minKSum[node];
}
Integer.MAX_VALUE;
}
(l + r) / ;
Integer.MAX_VALUE;
(ql <= mid) {
result = Math.min(result, queryMinKSum(node * , l, mid, ql, Math.min(qr, mid)));
}
(qr > mid) {
result = Math.min(result, queryMinKSum(node * + , mid + , r, Math.max(ql, mid + ), qr));
}
(ql <= mid && qr > mid) {
Math.max(ql, mid - k + );
Math.min(qr, mid + k - );
( leftStart; start <= mid && start + k - <= rightEnd; start++) {
start + k - ;
(end <= qr && end >= ql + k - ) {
result = Math.min(result, querySum(start, end));
}
}
}
result;
}
{
querySum(, , n, l, r);
}
{
(ql > qr) ;
(ql <= l && r <= qr) sum[node];
(l + r) / ;
;
(ql <= mid) result += querySum(node * , l, mid, ql, Math.min(qr, mid));
(qr > mid) result += querySum(node * + , mid + , r, Math.max(ql, mid + ), qr);
result;
}
}
IOException {
( (System.in));
String[] firstLine = br.readLine().split();
Integer.parseInt(firstLine[]);
Integer.parseInt(firstLine[]);
Integer.parseInt(firstLine[]);
[] arr = [N + ];
String[] arrStr = br.readLine().split();
( ; i <= N; i++) {
arr[i] = Integer.parseInt(arrStr[i - ]);
}
(N, K, arr);
( ; i < L; i++) {
String[] command = br.readLine().split();
command[];
Integer.parseInt(command[]);
Integer.parseInt(command[]);
(type.equals()) {
segTree.update(, , N, x, y);
} (type.equals()) {
segTree.update(, , N, x, -y);
} (type.equals()) {
segTree.queryMinKSum(, , N, x, y - K + );
System.out.println(result);
}
}
}
}
int
int
int
this
this
new
int
4
new
int
4
1
1
void
build
(int node, int l, int r, int[] arr)
if
1
return
int
mid
=
2
2
2
1
1
2
2
1
if
1
2
2
1
if
1
int
leftStart
=
2
for
int
start
=
1
int
end
=
1
if
else
void
update
(int node, int l, int r, int idx, int delta)
if
if
1
return
int
mid
=
2
if
2
else
2
1
1
2
2
1
if
1
2
2
1
if
1
int
leftStart
=
2
for
int
start
=
1
int
end
=
1
if
else
int
queryMinKSum
(int node, int l, int r, int ql, int qr)
if
1
return
if
if
1
return
return
int
mid
=
2
int
result
=
if
2
if
2
1
1
1
if
int
leftStart
=
2
int
rightEnd
=
1
for
int
start
=
1
int
end
=
1
if
1
return
int
querySum
(int l, int r)
return
1
1
int
querySum
(int node, int l, int r, int ql, int qr)
if
return
0
if
return
int
mid
=
2
int
result
=
0
if
2
if
2
1
1
1
return
public
static
void
main
(String[] args)
throws
BufferedReader
br
=
new
BufferedReader
new
InputStreamReader
" "
int
N
=
0
int
K
=
1
int
L
=
2
int
new
int
1
" "
for
int
i
=
1
1
SegmentTree
segTree
=
new
SegmentTree
for
int
i
=
0
" "
String
type
=
0
int
x
=
1
int
y
=
2
if
"Add"
1
1
else
if
"Sub"
1
1
else
if
"Query"
int
result
=
1
1
1
Python 实现
import sys
class SegmentTree:
def __init__(self, n, k, arr):
self.n = n
self.k = k
self.sum = [0] * (4 * n)
self.minKSum = [float('inf')] * (4 * n)
self.build(1, 1, n, arr)
def build(self, node, l, r, arr):
if l == r:
self.sum[node] = arr[l]
self.minKSum[node] = arr[l] if self.k == 1 else float('inf')
return
mid = (l + r) // 2
self.build(node * 2, l, mid, arr)
self.build(node * 2 + 1, mid + 1, r, arr)
self.sum[node] = self.sum[node * 2] + self.sum[node * 2 + 1]
if r - l + 1 >= self.k:
self.minKSum[node] = min(self.minKSum[node * 2], self.minKSum[node * 2 + 1])
if mid - l + 1 >= self.k - (r - mid):
left_start = max(l, mid - self.k + 2)
for start in range(left_start, mid + 1):
end = start + self.k - 1
if end <= r:
self.minKSum[node] = min(self.minKSum[node], self._query_sum(start, end))
else:
self.minKSum[node] = float('inf')
def update(self, node, l, r, idx, delta):
if l == r:
self.sum[node] += delta
if self.k == 1:
self.minKSum[node] = self.sum[node]
return
mid = (l + r) // 2
if idx <= mid:
self.update(node * 2, l, mid, idx, delta)
else:
self.update(node * 2 + 1, mid + 1, r, idx, delta)
self.sum[node] = self.sum[node * 2] + self.sum[node * 2 + 1]
if r - l + 1 >= self.k:
self.minKSum[node] = min(self.minKSum[node * 2], self.minKSum[node * 2 + 1])
if mid - l + 1 >= self.k - (r - mid):
left_start = max(l, mid - self.k + 2)
for start in range(left_start, mid + 1):
end = start + self.k - 1
if end <= r:
self.minKSum[node] = min(self.minKSum[node], self._query_sum(start, end))
else:
self.minKSum[node] = float('inf')
def query_min_k_sum(self, node, l, r, ql, qr):
if ql > qr or r - l + 1 < self.k:
return float('inf')
if ql <= l and r <= qr:
if r - l + 1 >= self.k:
return self.minKSum[node]
return float('inf')
mid = (l + r) // 2
result = float('inf')
if ql <= mid:
result = min(result, self.query_min_k_sum(node * 2, l, mid, ql, min(qr, mid)))
if qr > mid:
result = min(result, self.query_min_k_sum(node * 2 + 1, mid + 1, r, max(ql, mid + 1), qr))
if ql <= mid and qr > mid:
left_start = max(ql, mid - self.k + 2)
right_end = min(qr, mid + self.k - 1)
for start in range(left_start, mid + 1):
end = start + self.k - 1
if end <= qr and end >= ql + self.k - 1:
result = min(result, self._query_sum(start, end))
return result
def _query_sum(self, l, r):
return self._query_sum_helper(1, 1, self.n, l, r)
def _query_sum_helper(self, node, l, r, ql, qr):
if ql > qr: return 0
if ql <= l and r <= qr: return self.sum[node]
mid = (l + r) // 2
result = 0
if ql <= mid: result += self._query_sum_helper(node * 2, l, mid, ql, min(qr, mid))
if qr > mid: result += self._query_sum_helper(node * 2 + 1, mid + 1, r, max(ql, mid + 1), qr)
return result
def main():
data = sys.stdin.read().strip().split()
idx = 0
N = int(data[idx]); idx += 1
K = int(data[idx]); idx += 1
L = int(data[idx]); idx += 1
arr = [0] * (N + 1)
for i in range(1, N + 1):
arr[i] = int(data[idx]); idx += 1
seg_tree = SegmentTree(N, K, arr)
results = []
for _ in range(L):
cmd = data[idx]; idx += 1
x = int(data[idx]); idx += 1
y = int(data[idx]); idx += 1
if cmd == "Add":
seg_tree.update(1, 1, N, x, y)
elif cmd == "Sub":
seg_tree.update(1, 1, N, x, -y)
elif cmd == "Query":
result = seg_tree.query_min_k_sum(1, 1, N, x, y - K + 1)
results.append(str(result))
print("\n".join(results))
if __name__ == "__main__":
main()
C++ 实现
#include <iostream>
#include <vector>
#include <string>
#include <climits>
#include <algorithm>
using namespace std;
class SegmentTree {
private:
int n, k;
vector<int> sum;
vector<int> minKSum;
void build(int node, int l, int r, vector<int>& arr) {
if (l == r) {
sum[node] = arr[l];
minKSum[node] = (k == 1) ? arr[l] : INT_MAX;
return;
}
int mid = (l + r) / 2;
build(node * 2, l, mid, arr);
build(node * 2 + 1, mid + 1, r, arr);
sum[node] = sum[node * 2] + sum[node * 2 + 1];
if (r - l + 1 >= k) {
minKSum[node] = min(minKSum[node * 2], minKSum[node * 2 + 1]);
if (mid - l + 1 >= k - (r - mid)) {
int leftStart = max(l, mid - k + 2);
for (int start = leftStart; start <= mid; start++) {
int end = start + k - 1;
if (end <= r) {
minKSum[node] = min(minKSum[node], querySum(start, end));
}
}
}
} else {
minKSum[node] = INT_MAX;
}
}
int querySum(int l, int r) {
return querySum(1, 1, n, l, r);
}
int querySum(int node, int l, int r, int ql, int qr) {
if (ql > qr) return 0;
if (ql <= l && r <= qr) return sum[node];
int mid = (l + r) / 2;
int result = 0;
if (ql <= mid) result += querySum(node * 2, l, mid, ql, min(qr, mid));
if (qr > mid) result += querySum(node * 2 + 1, mid + 1, r, max(ql, mid + 1), qr);
return result;
}
public:
SegmentTree(int n, int k, vector<int>& arr) : n(n), k(k) {
sum.resize(4 * n);
minKSum.resize(4 * n, INT_MAX);
build(1, 1, n, arr);
}
void update(int node, int l, int r, int idx, int delta) {
if (l == r) {
sum[node] += delta;
if (k == 1) {
minKSum[node] = sum[node];
}
return;
}
int mid = (l + r) / 2;
if (idx <= mid) {
update(node * 2, l, mid, idx, delta);
} else {
update(node * 2 + 1, mid + 1, r, idx, delta);
}
sum[node] = sum[node * 2] + sum[node * 2 + 1];
if (r - l + 1 >= k) {
minKSum[node] = min(minKSum[node * 2], minKSum[node * 2 + 1]);
if (mid - l + 1 >= k - (r - mid)) {
int leftStart = max(l, mid - k + 2);
for (int start = leftStart; start <= mid; start++) {
int end = start + k - 1;
if (end <= r) {
minKSum[node] = min(minKSum[node], querySum(start, end));
}
}
}
} else {
minKSum[node] = INT_MAX;
}
}
int queryMinKSum(int node, int l, int r, int ql, int qr) {
if (ql > qr || r - l + 1 < k) {
return INT_MAX;
}
if (ql <= l && r <= qr) {
if (r - l + 1 >= k) {
return minKSum[node];
}
return INT_MAX;
}
int mid = (l + r) / 2;
int result = INT_MAX;
if (ql <= mid) {
result = min(result, queryMinKSum(node * 2, l, mid, ql, min(qr, mid)));
}
if (qr > mid) {
result = min(result, queryMinKSum(node * 2 + 1, mid + 1, r, max(ql, mid + 1), qr));
}
if (ql <= mid && qr > mid) {
int leftStart = max(ql, mid - k + 2);
int rightEnd = min(qr, mid + k - 1);
for (int start = leftStart; start <= mid; start++) {
int end = start + k - 1;
if (end <= qr && end >= ql + k - 1) {
result = min(result, querySum(start, end));
}
}
}
return result;
}
};
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int N, K, L;
cin >> N >> K >> L;
vector<int> arr(N + 1);
for (int i = 1; i <= N; i++) {
cin >> arr[i];
}
SegmentTree segTree(N, K, arr);
for (int i = 0; i < L; i++) {
string cmd;
int x, y;
cin >> cmd >> x >> y;
if (cmd == "Add") {
segTree.update(1, 1, N, x, y);
} else if (cmd == "Sub") {
segTree.update(1, 1, N, x, -y);
} else if (cmd == "Query") {
int result = segTree.queryMinKSum(1, 1, N, x, y - K + 1);
cout << result << "\n";
}
}
return 0;
}
JavaScript 实现
const readline = require('readline');
class SegmentTree {
constructor(n, k, arr) {
this.n = n;
this.k = k;
this.sum = new Array(4 * n).fill(0);
this.minKSum = new Array(4 * n).fill(Infinity);
this.build(1, 1, n, arr);
}
build(node, l, r, arr) {
if (l === r) {
this.sum[node] = arr[l];
this.minKSum[node] = (this.k === 1) ? arr[l] : Infinity;
return;
}
const mid = Math.floor((l + r) / 2);
this.build(node * 2, l, mid, arr);
this.build(node * 2 + 1, mid + 1, r, arr);
this.sum[node] = this.sum[node * 2] + this.sum[node * 2 + 1];
if (r - l + 1 >= this.k) {
this.minKSum[node] = Math.min(this.minKSum[node * 2], this.minKSum[node * 2 + 1]);
if (mid - l + 1 >= this.k - (r - mid)) {
const leftStart = Math.max(l, mid - this.k + 2);
for (let start = leftStart; start <= mid; start++) {
const end = start + this.k - 1;
if (end <= r) {
this.minKSum[node] = Math.min(this.minKSum[node], this._querySum(start, end));
}
}
}
} else {
this.minKSum[node] = Infinity;
}
}
update(node, l, r, idx, delta) {
if (l === r) {
this.sum[node] += delta;
if (this.k === 1) {
this.minKSum[node] = this.sum[node];
}
return;
}
const mid = Math.floor((l + r) / 2);
if (idx <= mid) {
this.update(node * 2, l, mid, idx, delta);
} else {
this.update(node * 2 + 1, mid + 1, r, idx, delta);
}
this.sum[node] = this.sum[node * 2] + this.sum[node * 2 + 1];
if (r - l + 1 >= this.k) {
this.minKSum[node] = Math.min(this.minKSum[node * 2], this.minKSum[node * 2 + 1]);
if (mid - l + 1 >= this.k - (r - mid)) {
const leftStart = Math.max(l, mid - this.k + 2);
for (let start = leftStart; start <= mid; start++) {
const end = start + this.k - 1;
if (end <= r) {
this.minKSum[node] = Math.min(this.minKSum[node], this._querySum(start, end));
}
}
}
} else {
this.minKSum[node] = Infinity;
}
}
queryMinKSum(node, l, r, ql, qr) {
if (ql > qr || r - l + 1 < this.k) {
return Infinity;
}
if (ql <= l && r <= qr) {
if (r - l + 1 >= this.k) {
return this.minKSum[node];
}
return Infinity;
}
const mid = Math.floor((l + r) / 2);
let result = Infinity;
if (ql <= mid) {
result = Math.min(result, this.queryMinKSum(node * 2, l, mid, ql, Math.min(qr, mid)));
}
if (qr > mid) {
result = Math.min(result, this.queryMinKSum(node * 2 + 1, mid + 1, r, Math.max(ql, mid + 1), qr));
}
if (ql <= mid && qr > mid) {
const leftStart = Math.max(ql, mid - this.k + 2);
const rightEnd = Math.min(qr, mid + this.k - 1);
for (let start = leftStart; start <= mid; start++) {
const end = start + this.k - 1;
if (end <= qr && end >= ql + this.k - 1) {
result = Math.min(result, this._querySum(start, end));
}
}
}
return result;
}
_querySum(l, r) {
return this._querySumHelper(1, 1, this.n, l, r);
}
_querySumHelper(node, l, r, ql, qr) {
if (ql > qr) return 0;
if (ql <= l && r <= qr) return this.sum[node];
const mid = Math.floor((l + r) / 2);
let result = 0;
if (ql <= mid) result += this._querySumHelper(node * 2, l, mid, ql, Math.min(qr, mid));
if (qr > mid) result += this._querySumHelper(node * 2 + 1, mid + 1, r, Math.max(ql, mid + 1), qr);
return result;
}
}
async function main() {
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
const lines = [];
for await (const line of rl) {
lines.push(line);
}
const firstLine = lines[0].split(' ').map(Number);
const N = firstLine[0];
const K = firstLine[1];
const L = firstLine[2];
const arr = [0];
lines[1].split(' ').forEach(val => arr.push(Number(val)));
const segTree = new SegmentTree(N, K, arr);
const results = [];
for (let i = 0; i < L; i++) {
const [cmd, xStr, yStr] = lines[2 + i].split(' ');
const x = parseInt(xStr);
const y = parseInt(yStr);
if (cmd === "Add") {
segTree.update(1, 1, N, x, y);
} else if (cmd === "Sub") {
segTree.update(1, 1, N, x, -y);
} else if (cmd === "Query") {
const result = segTree.queryMinKSum(1, 1, N, x, y - K + 1);
results.push(result.toString());
}
}
console.log(results.join('\n'));
rl.close();
}
main().catch(console.error);
C 实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
typedef struct {
int n, k;
int* sum;
int* minKSum;
} SegmentTree;
void build(SegmentTree* st, int node, int l, int r, int* arr) {
if (l == r) {
st->sum[node] = arr[l];
st->minKSum[node] = (st->k == 1) ? arr[l] : INT_MAX;
return;
}
int mid = (l + r) / 2;
build(st, node * 2, l, mid, arr);
build(st, node * 2 + 1, mid + 1, r, arr);
st->sum[node] = st->sum[node * 2] + st->sum[node * 2 + 1];
if (r - l + 1 >= st->k) {
st->minKSum[node] = min(st->minKSum[node * 2], st->minKSum[node * 2 + 1]);
if (mid - l + 1 >= st->k - (r - mid)) {
int leftStart = max(l, mid - st->k + 2);
for (int start = leftStart; start <= mid; start++) {
int end = start + st->k - 1;
if (end <= r) {
int sum = 0;
for (int i = start; i <= end; i++) {
sum += arr[i];
}
st->minKSum[node] = min(st->minKSum[node], sum);
}
}
}
} else {
st->minKSum[node] = INT_MAX;
}
}
SegmentTree* createSegmentTree(int n, int k, int* arr) {
SegmentTree* st = (SegmentTree*)malloc(sizeof(SegmentTree));
st->n = n;
st->k = k;
st->sum = (int*)malloc(4 * n * sizeof(int));
st->minKSum = (int*)malloc(4 * n * sizeof(int));
for (int i = 0; i < 4 * n; i++) {
st->sum[i] = 0;
st->minKSum[i] = INT_MAX;
}
build(st, 1, 1, n, arr);
return st;
}
int querySum(SegmentTree* st, int node, int l, int r, int ql, int qr) {
if (ql > qr) return 0;
if (ql <= l && r <= qr) return st->sum[node];
int mid = (l + r) / 2;
int result = 0;
if (ql <= mid) result += querySum(st, node * 2, l, mid, ql, min(qr, mid));
if (qr > mid) result += querySum(st, node * 2 + 1, mid + 1, r, max(ql, mid + 1), qr);
return result;
}
void update(SegmentTree* st, int node, int l, int r, int idx, int delta, int* arr) {
if (l == r) {
st->sum[node] += delta;
arr[l] += delta;
if (st->k == 1) {
st->minKSum[node] = st->sum[node];
}
return;
}
int mid = (l + r) / 2;
if (idx <= mid) {
update(st, node * 2, l, mid, idx, delta, arr);
} else {
update(st, node * 2 + 1, mid + 1, r, idx, delta, arr);
}
st->sum[node] = st->sum[node * 2] + st->sum[node * 2 + 1];
if (r - l + 1 >= st->k) {
st->minKSum[node] = min(st->minKSum[node * 2], st->minKSum[node * 2 + 1]);
if (mid - l + 1 >= st->k - (r - mid)) {
int leftStart = max(l, mid - st->k + 2);
for (int start = leftStart; start <= mid; start++) {
int end = start + st->k - 1;
if (end <= r) {
int sum = 0;
for (int i = start; i <= end; i++) {
sum += arr[i];
}
st->minKSum[node] = min(st->minKSum[node], sum);
}
}
}
} else {
st->minKSum[node] = INT_MAX;
}
}
int queryMinKSum(SegmentTree* st, int node, int l, int r, int ql, int qr, int* arr) {
if (ql > qr || r - l + 1 < st->k) {
return INT_MAX;
}
if (ql <= l && r <= qr) {
if (r - l + 1 >= st->k) {
return st->minKSum[node];
}
return INT_MAX;
}
int mid = (l + r) / 2;
int result = INT_MAX;
if (ql <= mid) {
result = min(result, queryMinKSum(st, node * 2, l, mid, ql, min(qr, mid), arr));
}
if (qr > mid) {
result = min(result, queryMinKSum(st, node * 2 + 1, mid + 1, r, max(ql, mid + 1), qr, arr));
}
if (ql <= mid && qr > mid) {
int leftStart = max(ql, mid - st->k + 2);
int rightEnd = min(qr, mid + st->k - 1);
for (int start = leftStart; start <= mid; start++) {
int end = start + st->k - 1;
if (end <= qr && end >= ql + st->k - 1) {
int sum = 0;
for (int i = start; i <= end; i++) {
sum += arr[i];
}
result = min(result, sum);
}
}
}
return result;
}
void freeSegmentTree(SegmentTree* st) {
free(st->sum);
free(st->minKSum);
free(st);
}
int main() {
int N, K, L;
scanf("%d %d %d", &N, &K, &L);
int* arr = (int*)malloc((N + 1) * sizeof(int));
for (int i = 1; i <= N; i++) {
scanf("%d", &arr[i]);
}
SegmentTree* st = createSegmentTree(N, K, arr);
for (int i = 0; i < L; i++) {
char cmd[10];
int x, y;
scanf("%s %d %d", cmd, &x, &y);
if (strcmp(cmd, "Add") == 0) {
update(st, 1, 1, N, x, y, arr);
} else if (strcmp(cmd, "Sub") == 0) {
update(st, 1, 1, N, x, -y, arr);
} else if (strcmp(cmd, "Query") == 0) {
int result = queryMinKSum(st, 1, 1, N, x, y - K + 1, arr);
printf("%d\n", result);
}
}
free(arr);
freeSegmentTree(st);
return 0;
}
相关免费在线工具
- 加密/解密文本
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
- Keycode 信息
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
- Escape 与 Native 编解码
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
- JavaScript / HTML 格式化
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
- JavaScript 压缩与混淆
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
- Gemini 图片去水印
基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online