CF1420C2 Pokémon Army加强版

原题比较捞,直接给一个加强版吧
题意:
维护一个序列,支持以下操作
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;
}
上一篇:Pokémon Army (easy version) CodeForces - 1420C1 dp


下一篇:C1. Pokémon Army (easy version) 解析(DP)