原题比较捞,直接给一个加强版吧
题意:
维护一个序列,支持以下操作
1.区间赋值
2.区间加法
3.区间查询权值最大的+-子序列
+-子序列的权值定义为:\(a_{b_1}-a_{b_2}+a_{b_3}-a_{b_4}.....\)
sol:
考虑不带修改的话,做法大概就是个dp
然后带上修改的话显然就是考虑类似ddp的那种数据结构维护dp数组
思考一下
发现需要维护4个东西
a,b,c,d
分别表示
在一个区间中
选出一个+-子序列的最大值
a:+开头 +结尾
b:+开头 -结尾
c:-开头 +结尾
d:-开头 -结尾
然后合并的话也非常好像,保证连接点处+-符号不同即可
代码的话只写了一个单点修改+区间查询
实际上加上区间修改也是非常简单的
首先赋值没什么好说的,下放标记时考虑清除加法标记即可
然后时区间加法
稍微研究一下就能明白加法对不同子序列的影响
a(++):ans+k
b(+-):ans不变
c(-+):ans不变
d(--):ans-k
按照这个思路去维护即可
#include<bits/stdc++.h>
#define N 550000
#define eps 1e-7
#define db double
#define ll long long
#define ldb long double
#define ull unsigned long long
using namespace std;
inline ll read()
{
char ch=0;
ll x=0,flag=1;
while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
return x*flag;
}
const ll inf=1e11+7;
ll f[N];
struct node{ll a,b,c,d;};
node operator+(node x,node y)
{
node ans;
ans.a=max(max(x.a,y.a),max(x.a+y.c,x.b+y.a));
ans.b=max(max(x.b,y.b),max(x.a+y.d,x.b+y.b));
ans.c=max(max(x.c,y.c),max(x.c+y.c,x.d+y.a));
ans.d=max(max(x.d,y.d),max(x.c+y.d,x.d+y.b));
return ans;
}
struct Segment_Tree
{
#define lson o<<1
#define rson o<<1|1
#define mid ((l+r)>>1)
node t[N*4];
inline void pushup(ll o){t[o]=t[lson]+t[rson];}
void build(ll o,ll l,ll r)
{
if(l==r)return (void)(t[o]=(node){+f[l],-inf,-inf,-f[r]});
build(lson,l,mid);build(rson,mid+1,r);pushup(o);
}
void optset(ll o,ll l,ll r,ll q,ll x)
{
if(l==r)return (void)(t[o]=(node){+x,-inf,-inf,-x});
if(q<=mid)optset(lson,l,mid,q,x);else optset(rson,mid+1,r,q,x);
pushup(o);
}
node query(ll o,ll l,ll r,ll ql,ll qr)
{
if(ql<=l&&r<=qr)return t[o];
bool flag1=(ql<=mid),flag2=(qr>mid);
if(flag1&&flag2)return query(lson,l,mid,ql,qr)+query(rson,mid+1,r,ql,qr);
else
{
if(flag1)return query(lson,l,mid,ql,qr);
if(flag2)return query(rson,mid+1,r,ql,qr);
}
}
}T;
void work()
{
ll n=read(),qnum=read();
for(ll i=1;i<=n;i++)f[i]=read();
T.build(1,1,n);
printf("%lld\n",T.query(1,1,n,1,n).a);
for(ll i=1;i<=qnum;i++)
{
ll x=read(),y=read();
T.optset(1,1,n,x,f[y]);
T.optset(1,1,n,y,f[x]);
printf("%lld\n",T.query(1,1,n,1,n).a);
swap(f[x],f[y]);
}
}
int main()
{
ll t=read();
for(ll i=1;i<=t;i++)work();
return 0;
}