355 字
2 分钟
AtCoder ABC442_D: D - Swap and Range Sum Editorial
AtCoder
2026-01-27

题目链接#

https://atcoder.jp/contests/abc442/tasks/abc442_d

题目大意#

给定一个长度为 NN 的整数序列 A=(A1,A2,,AN)A = (A_1, A_2, \dots, A_N)

你需要按顺序处理 QQ 个查询,查询分为以下两种类型:

  • 修改操作 1 x:交换序列中第 xx 个元素 AxA_x 和第 x+1x+1 个元素 Ax+1A_{x+1} 的值(其中 1x<N1 \le x < N)。
  • 查询操作 2 l r:计算并输出区间 [l,r][l, r] 内所有元素的和,即 i=lrAi\sum_{i=l}^{r} A_i

数据范围与约束:

  • 2N2×1052 \le N \le 2 \times 10^5
  • 1Q5×1051 \le Q \le 5 \times 10^5

解题思路#

对于此题,我们需要考虑交换 xxx+1x+1 会对前缀和造成什么后果。

sumsum 为前缀和数组。

  • 对于 1ix11 \le i \le x-1sumisum_i 还是和原来未交换的结果一致,为 j=1iAj\sum_{j=1}^{i} A_j
  • 对于 ix+1i \ge x+1sumisum_i 也和原来未交换的结果一致(因为集合元素没变,只是顺序变了),为 j=1iAj\sum_{j=1}^{i} A_j

受到影响的只有 sumxsum_x

  • sumx=j=1xAjsum_x = \sum_{j=1}^{x} A_j
  • 交换后的 sumx=j=1x1Aj+Ax+1sum_x = \sum_{j=1}^{x-1} A_j + A_{x+1}

结论:

  1. operator == 1 时,我们只需要更新 sumxsum_x,并记得在原数组中交换 AxA_xAx+1A_{x+1}
  2. operator == 2 时,正常利用前缀和计算区间和即可。

代码实现#

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
ll sum[N], a[N];
int n, q, op, l, r, x;
int main(){
scanf("%d%d", &n, &q);
for(int i=1;i<=n;i++) {
scanf("%lld", &a[i]);
sum[i]=sum[i-1]+a[i];
}
while(q--){
scanf("%d", &op);
if(op==1) {
scanf("%d", &x);
sum[x]=sum[x-1]+a[x+1];
swap(a[x], a[x+1]);
}
else {
scanf("%d%d", &l, &r);
printf("%lld\n", sum[r]-sum[l-1]);
}
}
return 0;
}
AtCoder ABC442_D: D - Swap and Range Sum Editorial
https://shenyize.com/posts/atcoder/abc442d/
作者
Shenyize
发布于
2026-01-27
许可协议
CC BY-NC-SA 4.0