DOS Card
写在前面:
此篇题解维护了 12 12 12个信息,是拆分式子的写法。
个人感觉相较与官方题解维护信息多,但思维简单实现快不易出错。
拆分式子即暴力考虑所有更新情况(和线段树解决多维最值曼哈顿距离拆分绝对值类似)
思路:
式子是明显的平方差式子。
如果只求单个式子的最值维护两个最值和答案不断更新即可。
如果分开考虑每次求一个式子的最值不好操作。(有重复数的存在)
式子存在下标的位置限制只有两种组成情况。
+
+
−
−
,
+
−
+
−
++--,+-+-
++−−,+−+−
不断拆分。
+
−
−
,
+
+
−
,
+
−
+
,
−
+
−
,
+--, ++- ,+-+, -+-,
+−−,++−,+−+,−+−,
+
+
,
+
−
,
−
+
,
−
−
++, +-, -+, --
++,+−,−+,−−
+
,
−
+,-
+,−
上层可以由下层更新,区间合并时只考虑区间与区间之间的贡献。
符号给到数字,全为加法维护
m
a
x
max
max即可。
Code:
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <vector>
#include <string>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <climits>
//#include <unordered_map>
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
#define PI 3.1415926535898
using namespace std;
const int N=2e5+10;
ll n,q;
ll val[N];
struct PW{
int l,r;
ll ans1,ans2; // ++-- +-+-
ll a,b; // + -
ll c,d,e,f; // ++ +- -+ --
ll g,h,i,j; // +-- ++- +-+ -+-
}tr[N*4];
void pushup(PW &u,PW &l,PW &r){
u.ans1=max(l.ans1,r.ans1);
u.ans2=max(l.ans2,r.ans2);
u.a=max(l.a,r.a);
u.b=max(l.b,r.b);
u.c=max(l.c,r.c);
u.d=max(l.d,r.d);
u.e=max(l.e,r.e);
u.f=max(l.f,r.f);
u.g=max(l.g,r.g);
u.h=max(l.h,r.h);
u.i=max(l.i,r.i);
u.j=max(l.j,r.j);
u.ans1=max({u.ans1,l.a+r.g,l.h+r.b,l.c+r.f});
u.ans2=max({u.ans2,l.i+r.b,l.a+r.j,l.d+r.d});
u.c=max(u.c,l.a+r.a);
u.d=max(u.d,l.a+r.b);
u.e=max(u.e,l.b+r.a);
u.f=max(u.f,l.b+r.b);
u.g=max({u.g,l.a+r.f,l.d+r.b});
u.h=max({u.h,l.a+r.d,l.c+r.b});
u.i=max({u.i,l.a+r.e,l.d+r.a});
u.j=max({u.j,l.b+r.d,l.e+r.b});
}
void pushup(int id){
pushup(tr[id],tr[id<<1],tr[id<<1|1]);
}
void init(PW &s){
s.ans1=s.ans2=s.a=s.b=s.c=s.d=s.e=s.f=s.g=s.h=s.i=s.j=-1e18;
}
void build(int id,int l,int r){
init(tr[id]); tr[id].l=l,tr[id].r=r;
if(l==r){
tr[id].a=val[l];
tr[id].b=-val[l];
}
else{
int mid=(l+r)>>1;
build(id<<1,l,mid),build(id<<1|1,mid+1,r);
pushup(id);
}
}
PW query(int id,int l,int r){
if(tr[id].l>=l&&tr[id].r<=r){
return tr[id];
}
else{
int mid=(tr[id].l+tr[id].r)>>1;
if(r<=mid) return query(id<<1,l,r);
else if(l>mid) return query(id<<1|1,l,r);
else{
PW s1=query(id<<1,l,r);
PW s2=query(id<<1|1,l,r);
PW s3;
pushup(s3,s1,s2);
return s3;
}
}
}
int main(){
guo312;
int t; cin>>t;
while(t--){
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>val[i];
val[i]*=val[i];
}
build(1,1,n);
while(q--){
int l,r; cin>>l>>r;
auto it=query(1,l,r);
cout<<max(it.ans1,it.ans2)<<endl;
}
}
return 0;
}