题意就是给你一串数字,让你找出一串序列(可以不连续),使他们+,-,+,-...运算后这样的结果最大
比如
1 2 5 4 3 6 7
最大结果为5−3+7=9
hard version较easy version区别是hard version有最大为3e5次的交换,即交换两个数字然后每次交换输出结果
easy version没有交换,简单很多,可以用dp来做
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10;
ll a[N];
int main(){
int T;scanf("%d",&T);
while(T--){
memset(a,0,sizeof(a));
ll t1=0,t2=0;
int n,q;scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
t1=max(a[1],a[2]);
t2=max(a[1]-a[2],(ll)0);
for(int i=3;i<=n;i++){
t1=max(t1,max(t2+a[i],a[i]));
t2=max(t2,max(t1-a[i],(ll)0));
}
printf("%lld\n",max(t1,t2));
}
return 0;
}
但是这样的hard version有了交换之后就没办法入手了,可能是我太菜了。。。
赛后看别人的AC代码,发现了一个神奇的规律
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10;
ll a[N];
ll s(int i){
return max((ll)0,a[i]-a[i-1]);
}
int main(){
//freopen("in.txt","r",stdin);
int T;scanf("%d",&T);
while(T--){
ll ans=0;
int n,q;scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
ans+=s(i);
}
printf("%lld\n",ans);
}
return 0;
}
有了这样的规律之后对每次交换可以O(1)处理然后输出答案了
hard versionAC代码如下
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+10;
ll a[N];
ll s(int i){
return max((ll)0,a[i]-a[i-1]);
}
int main(){
//freopen("in.txt","r",stdin);
int T;scanf("%d",&T);
while(T--){
ll ans=0;
int n,q;scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++){
scanf("%lld",&a[i]);
ans+=s(i);
}
printf("%lld\n",ans);
while(q--){
int x,y;
scanf("%d%d",&x,&y);
ans-=s(x);
ans-=s(x+1);
if(y!=x+1) ans-=s(y);
if(y!=n) ans-=s(y+1);
swap(a[x],a[y]);
ans+=s(x);
ans+=s(x+1);
if(y!=x+1) ans+=s(y);
if(y!=n) ans+=s(y+1);
printf("%lld\n",ans);
}
}
return 0;
}