其他分享
首页 > 其他分享> > cf 1420 C Pokémon Army (hard version)

cf 1420 C Pokémon Army (hard version)

作者:互联网

简易版显然是dp了
加强版可以用差分(但我不会)
看到一种线段树的写法 比差分好写 讨论少
众所周知最大子列和是可以用线段树动态维护的
然后这题和最大子列和其实差不多
维护
++ +- -+ --这四种情况 然后合并就可以了
比赛的时候脑抽了 想着维护奇数和和偶数和可以
像这种需要合并的 我们都得清楚边界情况是啥 才能保证合并的准确性

#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
typedef long long ll;
struct node{
	ll zz,zf,fz,ff;
	int l,r;
}T[N<<2];
ll a[N];
const ll inf = 1e15;
#define ls id<<1
#define rs ls|1
void pushup(int id){
	T[id].zz=max({T[ls].zz,T[rs].zz,T[ls].zf+T[rs].zz,T[ls].zz+T[rs].fz});
	T[id].zf=max({T[ls].zf,T[rs].zf,T[ls].zz+T[rs].ff,T[ls].zf+T[rs].zf});
	T[id].fz=max({T[ls].fz,T[rs].fz,T[ls].ff+T[rs].zz,T[ls].fz+T[rs].fz});
	T[id].ff=max({T[ls].ff,T[rs].ff,T[ls].ff+T[rs].zf,T[ls].fz+T[rs].ff});
	//printf("l=%d r=%d\n",T[id].l,T[id].r);
	//printf("zz=%lld zf=%lld fz=%lld ff=%lld\n",T[id].zz,T[id].zf,T[id].fz,T[id].ff);
}
void build(int id,int l,int r){
	T[id].l=l,T[id].r=r;
	if(l==r){
		T[id].zz=a[l];
		T[id].zf=-inf;
		T[id].fz=-inf;
		T[id].ff=-a[l];
		return;
	}
	int mid = l+r>>1;
	build(ls,l,mid);build(rs,mid+1,r);
	pushup(id);
}
void update(int id,int pos,ll v){
	if(T[id].l==T[id].r){
		T[id].zz=v;
		T[id].zf=-inf;
		T[id].fz=-inf;
		T[id].ff=-v;
		return;
	}	
	int mid = T[id].l+T[id].r>>1;
	if(pos<=mid) update(ls,pos,v);
	else update(rs,pos,v);
	pushup(id);
}
int main(){
	int  t;
	scanf("%d",&t);
	while(t--){
		int n,q;
		scanf("%d%d",&n,&q);
		for(int i = 1; i <= n; i++) scanf("%lld",&a[i]);
		build(1,1,n);
		printf("%lld\n",T[1].zz);
		for(int i = 1; i <= q; i++){
			int l,r;
			scanf("%d%d",&l,&r);
			update(1,l,a[r]);
			update(1,r,a[l]);
			swap(a[l],a[r]);
			printf("%lld\n",T[1].zz);
		} 
	}
	return 0;
} 
/*
22
7 0
1 2 5 4 3 6 7
*/

标签:1420,Army,int,ll,hard,mid,zz,inf,id
来源: https://www.cnblogs.com/League-of-cryer/p/14299866.html