跳到主要内容
敌情监控:多语言实现区间连续 K 个营地最小兵力之和 | 极客日志
编程语言 java 算法
敌情监控:多语言实现区间连续 K 个营地最小兵力之和 综述由AI生成 一个敌情监控问题,要求在动态变化的 N 个营地中,快速查询任意区间内连续 K 个营地的最小兵力之和。支持单点增加或减少兵力的操作。文章提供了基于线段树的解决方案,维护区间和与长度为 K 的子区间最小和,并给出了 Java、Python、C++、JavaScript 和 C 五种语言的完整实现代码。
深海蔚蓝 发布于 2026/3/26 更新于 2026/5/12 24 浏览敌情监控:多语言实现区间连续 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