题意:给你一个序列,从左往右一次选择数字,奇数次选的符号为正,反之符号为负,问最后的最大值是多少,qwq这是简单版本的,然后难的版本多了一个修改,该修改是交换两个数的位置。
解题思路:如果是简单版本那么可以用dp来做,数组定义为考虑前i个 且轮到第i个的时候是奇数还是偶数次,难的版本有大佬说可以用线段树做,然而我并不会,然后看最优解在途中的表示,是先波峰再波谷 这样循环往复,然后画图发现竟然这个策略与(i>=1 && i<=n)zigema max(a[i]-a[i-1],0)等价,那么修改就很好办了,减去l和r对答案的贡献,再加上新的l和r对答案的贡献,当l=r+1的时候要特判一下不然会多减。
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>
using namespace std;
typedef long long ll;
const int N=300010;
int a[N];
int n,q;
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int t;
cin>>t;
while(t--)
{
cin >> n >> q;
for(int i=1;i<=n;i++)
cin >> a[i];
a[0]=0,a[n+1]=0;
ll res=0;
for(int i=1;i<=n;i++)
res+=max(a[i]-a[i-1],0);
cout<<res<<endl;
while(q--)
{
int l,r;
cin>>l>>r;
if(l==r)
{
cout<<res<<endl;
continue;
}
if(r==l+1)
{
res-=max(a[r]-a[l],0);
res-=max(a[r+1]-a[r],0);
res-=max(a[l]-a[l-1],0);
swap(a[l],a[r]);
res+=max(a[r]-a[l],0);
res+=max(a[r+1]-a[r],0);
res+=max(a[l]-a[l-1],0);
cout<<res<<endl;
continue;
}
res-=max(a[l]-a[l-1],0)+max(a[l+1]-a[l],0);
res-=max(a[r]-a[r-1],0)+max(a[r+1]-a[r],0);
swap(a[l],a[r]);
res+=max(a[r]-a[r-1],0)+max(a[r+1]-a[r],0);
res+=max(a[l]-a[l-1],0)+max(a[l+1]-a[l],0);
cout<<res<<endl;
}
}
return 0;
}