题意:给你一个序列,从左往右一次选择数字,奇数次选的符号为正,反之符号为负,问最后的最大值是多少,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;
}