线段树求最大子段和的板子
枚举每个长度为k的区间
// Problem: Maximum Subarray
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF1796D
// Memory Limit: 500 MB
// Time Limit: 2000 ms
//
// Powered by CP Editor (https://cpeditor.org)
#include<iostream>
#include<algorithm>
#define INF (1ll<<60)
using namespace std;
typedef long long ll;
const int N=2e5+9;
int a[N];
struct node{
int l,r;
ll lmx,rmx,sum;
ll ans;
}seg[N<<2];
ll tl(ll x){return x<<1;}
ll tr(ll x){return x<<1|1;}
void pushup(node &id,node &l,node &r){
id.sum=l.sum+r.sum;
id.lmx=max(l.lmx,l.sum+r.lmx);
id.rmx=max(r.rmx,r.sum+l.rmx);
id.ans=max(max(l.ans,r.ans),l.rmx+r.lmx);
}
void pushup(int id){
pushup(seg[id],seg[tl(id)],seg[tr(id)]);
}
void build(int id,int l,int r){
seg[id]={l,r,0,0,0,0};
if(l==r){
seg[id]={l,r,a[l],a[l],a[l],a[l]};
return;
}
int mid=(l+r)>>1;
build(tl(id),l,mid);
build(tr(id),mid+1,r);
pushup(id);
}
node query(int id,int l,int r){
if(seg[id].l>=l && seg[id].r<=r){
return seg[id];
}else{
int mid=(seg[id].l+seg[id].r)>>1;
if(mid>=r){
return query(tl(id),l,r);
}else if(mid<l){
return query(tr(id),l,r);
}else{
node res;
node left=query(tl(id),l,r);
node right=query(tr(id),l,r);
pushup(res,left,right);
return res;
}
}
}
void update(int id,int l,int r,int pos,ll v){
if(l==r){
ll t=seg[id].lmx+v;
seg[id]={l,r,t,t,t,t};
return;
}
int mid=(l+r)>>1;
if(mid>=pos){
update(tl(id),l,mid,pos,v);
}else{
update(tr(id),mid+1,r,pos,v);
}
pushup(id);
}
void solve(){
int n,k,x;
cin>>n>>k>>x;
if(x<0){
x=-x;
k=n-k;
}
for(int i=1;i<=n;i++){
cin>>a[i];
if(i<=k){
a[i]+=x;
}else{
a[i]-=x;
}
}
build(1,1,n);
ll ans=max(0ll,seg[1].ans);
for(int i=2;i<=n-k+1;i++){
update(1,1,n,i-1,-2*x);
update(1,1,n,i+k-1,2*x);
ans=max(ans,seg[1].ans);
}
cout<<ans<<'\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--){
solve();
}
return 0;
}