題意:輸入N,M,K。有N個點,每個點有一個值,然後有M個操作 0 x y 表示將x的值賦爲y; 1 x y 表示將x和y互換下位置(相應值也互換) ; 2 x y 表示詢問[x,y]內連續K個數和的最大值。
一開始想用每個點來建樹,發現不好維護區間內連續K個數的和的最大值。
但如果轉化一下,因爲K是定值,將[x,x+k-1]區間的和看做一個點,這樣以連續K個數和作爲點,共有N-K+1的點建樹。 變成了求線段樹區間最值問題。
於是單點更新,轉化爲了區間更新: 修改了點x處的值,則產生的影響區間爲 【max(1,x-k+1),min(n-k+1,x) 】。
#include <iostream>
#include <algorithm>
#include <cmath>
#include<functional>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <climits>//形如INT_MAX一類的
#define MAX 200050
#define INF 0x7FFFFFFF
#define L(x) x<<1
#define R(x) x<<1|1
# define eps 1e-5
using namespace std;
inline void RD(int &ret) {
char c;
int flag = 1 ;
do {
c = getchar();
if(c == '-')flag = -1 ;
} while(c < '0' || c > '9') ;
ret = c - '0';
while((c=getchar()) >= '0' && c <= '9')
ret = ret * 10 + ( c - '0' );
ret *= flag ;
}
void OT(int a) {
if(a < 0) {
putchar('-');
a = -a;
}
if(a >= 10)OT(a / 10);
putchar(a % 10 + '0');
}
int n,m,k;
struct node {
int l,r,mid;
int v,add;
}tr[MAX * 4];
int a[MAX],va[MAX];
void init() {
memset(va,0,sizeof(va));
}
void up(int x) {
tr[x].v = max(tr[L(x)].v, tr[R(x)].v);
}
void build(int l,int r,int x) {
tr[x].l = l;
tr[x].r = r;
tr[x].mid = (l + r) >> 1;
tr[x].add = 0;
if(l == r) {
tr[x].v = va[l];
return ;
}
build(l,tr[x].mid,L(x));
build(tr[x].mid+1,r,R(x));
up(x);
}
void down(int x) {
if(tr[x].add != 0) {
tr[L(x)].add += tr[x].add;
tr[R(x)].add += tr[x].add;
tr[L(x)].v += tr[x].add;
tr[R(x)].v += tr[x].add;
tr[x].add = 0;
}
}
void update(int l,int r,int x,int val) {
if(l <= tr[x].l && r >= tr[x].r) {
tr[x].add += val;
tr[x].v += val;
return ;
}
down(x);
int mid = tr[x].mid;
if(l <= mid) update(l,r,L(x),val);
if(r > mid) update(l,r,R(x),val);
up(x);
}
int query(int l,int r,int x) {
if(l <= tr[x].l && r >= tr[x].r) {
return tr[x].v;
}
down(x);
int mid = tr[x].mid;
if(r <= mid) return query(l,r,L(x));
else if(l > mid) return query(l,r,R(x));
else {
return max(query(l,mid,L(x)), query(mid+1,r,R(x)));
}
}
void test() {
int size = n - k + 1;
for(int i=1; i<=3 * size; i++) {
printf("%d %d %d %d\n",tr[i].l,tr[i].r,tr[i].v,tr[i].add);
}
}
int main() {
int T;
cin >> T;
while(T --) {
init();
scanf("%d%d%d",&n,&m,&k);
for(int i=1; i<=n; i++) RD(a[i]);
for(int i=1; i<=k; i++) va[1] += a[i];
for(int i=k+1; i<=n; i++) {
va[i - k + 1] = va[i - k] - a[i - k] + a[i];
}
build(1,n-k+1,1);
int b,c,d;
for(int i=0; i<m; i++) {
RD(b);RD(c);RD(d);
if(b == 0) {
int val = d - a[c];
update(max(1,c-k+1),min(n-k+1,c),1,val);
a[c] = d;
}
if(b == 1) {
if(c == d || a[c] == a[d]) continue;
int x1 = a[c] - a[d];
int x2 = a[d] - a[c];
update(max(1,c-k+1),min(n-k+1,c),1,x2);
update(max(1,d-k+1),min(n-k+1,d),1,x1);
swap(a[c],a[d]);
}
if(b == 2) {
OT(query(c,d-k+1,1));
puts("");
}
}
}
return 0;
}
/*
1
5 7 3
-1 2 -4 6 1
2 1 5
2 1 3
1 2 1
2 1 5
2 1 4
0 2 4
2 1 5
*/