此题神矣。。。一开始我先想的第二问。。。想到一个线段树做法。。。对于最优子序列的下标序列,i[2k]~i[2k+1]这段区间选一个最小值位置为pos再在pos~i[2k+1]选一个最大值,更新答案。。。再同样处理剩下的区间i[2k]~pos-1。。。数据随机的话O(lognlogn)但是。。。第一问的更新就成了瓶颈。。。
后来看了题解才知道。。。不能把i[2k]~i[2k+1]分为一组。。。要把i[2k-1]~i[2k]分为一组。。。第一问更新用差值。。。即设d[i]=u[i]-u[i-1],这样更新就只需更新最多2个点。。。
题解上细节错误太多了。。。但是想法是很明了的。。。由于把i[2k-1]~i[2k]分为一组。。。对于调整i[2k]~i[2k+1],即将d数组上对应负区间上操作,我们在d数组上建立线段树,查询sum和max就可以了。。。至于区间可操作性。。。只要不包含d[2]或d[n]即可。。。
这样一颗zkw线段树维护d数组。。。一颗splay维护所有负区间左右端点(包括不可操作区间)。。。一颗splay维护可操作负区间可贡献的权值。。。为了不使自己写迷糊了。。。将以上写成class或struct就可以了。。。11kb很好(不要被吓到了。。。只不过缩进很长而已。。。还有一些注释)。。。根本用不到那么多数据结构。。。有一点注意要时刻判断你在splay中查找到的值。。。以及zkw的修改和splay的修改的先后。。。
Code:总时间十个Case7.5S,标程9S+。。。双旋splay果然强大。。。
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
typedef long long ll;
const ll oo=1000000000;
class splayinter
{
private:
int rfs,rffs,rch,fs,ffs,root,size;
bool p,q;
int f[200005],son[200005][2],keyl[200005],keyr[200005];
inline void rotate(int s,bool t)
{
rfs=f[s],rffs=f[rfs],rch=son[s][t^1];
if (rffs)
if (son[rffs][0]==rfs) son[rffs][0]=s; else son[rffs][1]=s;
f[s]=rffs;
son[s][t^1]=rfs;
f[rfs]=s;
son[rfs][t]=rch;
if (rch) f[rch]=rfs;
}
inline void splay(int s)
{
if (!s) return;
fs=f[s],ffs=f[fs];
while (fs && (son[fs][0]==s || son[fs][1]==s))
{
if (ffs && (son[ffs][0]==fs || son[ffs][1]==fs))
{
p=(son[ffs][1]==fs);
q=(son[fs][1]==s);
if (p==q)
rotate(fs,p),rotate(s,q);
else
rotate(s,q),rotate(s,p);
}
else
if (son[fs][0]==s) rotate(s,0); else rotate(s,1);
fs=f[s],ffs=f[fs];
}
root=s;
}
public:
inline void effectkey(int pos,int &l,int &r)
{
l=keyl[pos];
r=keyr[pos];
}
inline int find(int key)
{
int now=root,last=0;
while (now)
{
last=now;
if ((keyl[now]<=key)&&(key<=keyr[now])) return now;
if (key<keyl[now]) now=son[now][0]; else now=son[now][1];
}
while (key<keyl[last]) last=f[last];
return last;
}
inline int find(int kl,int kr)
{
int now=root,last=0;
while (now)
{
last=now;
if ((keyl[now]<=kl)&&(kr<=keyr[now])) return now;
if (kr<keyl[now]) now=son[now][0]; else now=son[now][1];
}
while (kr<keyl[last]) last=f[last];
return last;
}
inline int findleft(int pos)
{
while (son[pos][0])
pos=son[pos][0];
return pos;
}
inline void insert(int kl,int kr)
{
if (kr<kl) return;
int pos=find(kl,kr);
if (!pos) return;
splay(pos);
int ch=son[pos][1];
son[pos][1]=++size;
f[size]=pos;
keyl[size]=kl;
keyr[size]=kr;
son[size][1]=ch;
if (ch) f[ch]=size;
}
inline void eraser(int pos)
{
if (!pos) return;
splay(pos);
int tmpch=son[pos][1];
if (!tmpch)
{
root=son[pos][0];
f[root]=0;
son[pos][0]=keyl[pos]=keyr[pos]=0;
}
else
{
f[tmpch]=0;
root=tmpch;
son[pos][1]=0;
int left=findleft(tmpch);
splay(left);
son[left][0]=son[pos][0];
if (f[son[pos][0]]) f[son[pos][0]]=left;
son[pos][0]=keyl[pos]=keyr[pos]=0;
}
}
inline void eraser(int kl,int kr)
{
if (kr<kl) return;
int pos=find(kl,kr);
if (keyl[pos]!=kl || keyr[pos]!=kr) return;
eraser(pos);
}
inline void creat()
{
root=1;
size=1;
memset(keyl,0,sizeof(keyl));
memset(keyr,0,sizeof(keyr));
memset(f,0,sizeof(f));
memset(son,0,sizeof(son));
keyl[1]=keyr[1]=1;
rfs=rffs=rch=fs=ffs=0;
p=q=0;
}
} splayi;
class splayval
{
private:
int rfs,rffs,rch,fs,ffs,root,size;
bool p,q;
int f[200005],son[200005][2],sums[200005];
ll val[200005],totv[200005];
inline void update(int s)
{
sums[s]=sums[son[s][0]]+sums[son[s][1]]+1;
totv[s]=totv[son[s][0]]+totv[son[s][1]]+val[s];
}
inline void rotate(int s,bool t)
{
rfs=f[s],rffs=f[rfs],rch=son[s][t^1];
if (rffs)
if (son[rffs][0]==rfs) son[rffs][0]=s; else son[rffs][1]=s;
f[s]=rffs;
son[s][t^1]=rfs;
f[rfs]=s;
son[rfs][t]=rch;
if (rch) f[rch]=rfs;
update(rfs);
}
inline void splay(int s)
{
if (!s) return;
fs=f[s],ffs=f[fs];
while (fs && (son[fs][0]==s || son[fs][1]==s))
{
if (ffs && (son[ffs][0]==fs || son[ffs][1]==fs))
{
p=(son[ffs][1]==fs);
q=(son[fs][1]==s);
if (p==q)
rotate(fs,p),rotate(s,q);
else
rotate(s,q),rotate(s,p);
}
else
if (son[fs][0]==s) rotate(s,0); else rotate(s,1);
fs=f[s],ffs=f[fs];
}
root=s;
update(s);
}
public:
inline int find(ll key)
{
int now=root,last=0;
while (now)
{
last=now;
if (val[now]==key) return now;
if (key<val[now]) now=son[now][0]; else now=son[now][1];
}
while (key<val[last]) last=f[last];
return last;
}
inline int findleft(int pos)
{
while (son[pos][0])
pos=son[pos][0];
return pos;
}
inline int mintime(ll key)
{
if (totv[root]<key) return -1;
int now=root,ans=0;
while (now && (key>0))
{
if (totv[son[now][1]]>=key)
now=son[now][1];
else
if (totv[son[now][1]]+val[now]>=key) return ans+sums[son[now][1]]+1;
else
{
ans+=(sums[son[now][1]]+1);
key-=(totv[son[now][1]]+val[now]);
now=son[now][0];
}
}
return ans;
}
inline void insert(ll va)
{
if (va<0) return;
int pos=find(va);
if (!pos) return;
splay(pos);
int ch=son[pos][1];
son[pos][1]=++size;
val[size]=va;
f[size]=pos;
son[size][1]=ch;
if (ch) f[ch]=size;
update(size);
update(pos);
}
inline void eraserpos(int pos)
{
if (!pos) return;
splay(pos);
int tmpch=son[pos][1];
if (!tmpch)
{
root=son[pos][0];
f[root]=0;
son[pos][0]=son[pos][1]=val[pos]=totv[pos]=sums[pos]=0;
}
else
{
f[tmpch]=0;
son[pos][1]=0;
root=tmpch;
int left=findleft(tmpch);
splay(left);
son[left][0]=son[pos][0];
if (son[pos][0]) f[son[pos][0]]=left;
son[pos][0]=val[pos]=totv[pos]=sums[pos]=0;
update(left);
}
}
inline void eraserkey(ll va)
{
int pos=find(va);
if ((!pos)||(va!=val[pos])) return;
eraserpos(pos);
}
inline void creat()
{
root=1;
size=1;
memset(val,0,sizeof(val));
memset(f,0,sizeof(f));
memset(son,0,sizeof(son));
memset(sums,0,sizeof(sums));
memset(totv,0,sizeof(totv));
rfs=rffs=rch=fs=ffs=0;
p=q=0;
}
} splayv;
class zkwinter
{
private:
ll maxt[262149],sumt[262149];
int mm;
inline ll max(ll a,ll b)
{
if (a>b) return a;
return b;
}
public:
inline ll askval(int l,int r)
{
l=l+mm-1;
r=r+mm+1;
ll ans1=0;
ll ans2=-oo;
while (l^r^1)
{
if (!(l&1))
{
ans1+=sumt[l^1];
if (maxt[l^1]>ans2) ans2=maxt[l^1];
}
if (r&1)
{
ans1+=sumt[r^1];
if (maxt[r^1]>ans2) ans2=maxt[r^1];
}
l>>=1;
r>>=1;
}
return ans1-ans2;
}
inline void modify(int pos,ll val)
{
pos+=mm;
maxt[pos]+=val;
sumt[pos]+=val;
pos>>=1;
while (pos)
{
maxt[pos]=max(maxt[pos<<1],maxt[(pos<<1)+1]);
sumt[pos]+=val;
pos>>=1;
}
}
inline void creat(ll *a,int n)
{
memset(maxt,0,sizeof(maxt));
memset(sumt,0,sizeof(sumt));
mm=1<<(int)(log2(n)+1);
while (mm<n) mm<<1;
maxt[mm]=-oo;
for (int i=1;i<=n;i++) maxt[i+mm]=sumt[i+mm]=a[i];
maxt[mm+1]=-oo;
for (int i=n+1+mm;i<=(mm<<1);i++) maxt[i]=-oo;
for (int i=mm-1;i>=1;i--) maxt[i]=max(maxt[i<<1],maxt[(i<<1)+1]),
sumt[i]=sumt[i<<1]+sumt[(i<<1)+1];
}
} zkw;
ll a[100005],b[100005],positive=0;
int task=0,q=0,n=0;
inline void init()
{
scanf("%d%d",&n,&q);
int i=0;
for (i=1;i<=n;i++)
scanf("%I64d",&a[i]);
int l=0,r=-1;
for (i=2;i<=n;i++) b[i]=a[i]-a[i-1];
zkw.creat(b,n);
for (i=2;i<=n;i++)
if (b[i]>0)
{
positive+=b[i];
if (r-l>=0)
{
splayi.insert(l,r);
if ((l!=2)&&(r!=n)) splayv.insert(-zkw.askval(l,r));
l=0,r=-1;
}
}
else
{
if ((b[i-1]>0) || (i==2)) l=i,r=i-1;
r++;
}
if (b[n]<0)
if (r-l>=0)
splayi.insert(l,r);
}
inline void add(int pos,ll val)
{
ll last=b[pos];
b[pos]+=val;
ll now=b[pos];
if (last>0)
if (now>0)
{
positive+=val;
zkw.modify(pos,val);//Case 1
}
else
{
positive-=last;
int nl=pos,nr=pos;
if (b[pos-1]<0)
{
int inter=splayi.find(pos-1),interl=0,interr=0;
splayi.effectkey(inter,interl,interr);
splayi.eraser(inter);
if (interl!=2) splayv.eraserkey(-zkw.askval(interl,interr));
nl=interl;
}
if (b[pos+1]<0)
{
int inter=splayi.find(pos+1),interl=0,interr=0;
splayi.effectkey(inter,interl,interr);
splayi.eraser(inter);
if (interr!=n) splayv.eraserkey(-zkw.askval(interl,interr));
nr=interr;
}
zkw.modify(pos,val);
splayi.insert(nl,nr);
if ((nl!=2)&&(nr!=n)) splayv.insert(-zkw.askval(nl,nr));
//Case 4
}
else
if (now>0)
{
positive+=now;
int inter=splayi.find(pos),interl=0,interr=0;
splayi.effectkey(inter,interl,interr);
splayi.eraser(inter);
if ((interl!=2)&&(interr!=n))
splayv.eraserkey(-zkw.askval(interl,interr));
zkw.modify(pos,val);
int l1=interl,r1=pos-1,l2=pos+1,r2=interr;
if (l1<=r1)
{
splayi.insert(l1,r1);
if (l1!=2) splayv.insert(-zkw.askval(l1,r1));
}
if (l2<=r2)
{
splayi.insert(l2,r2);
if (r2!=n) splayv.insert(-zkw.askval(l2,r2));
}
//Case 3
}
else
{
int inter=splayi.find(pos),interl=0,interr=0;
splayi.effectkey(inter,interl,interr);
if ((interl<=2)||(interr==n))
{
zkw.modify(pos,val);
return;
}
int nowsum=-zkw.askval(interl,interr);
splayv.eraserkey(nowsum);
zkw.modify(pos,val);
splayv.insert(-zkw.askval(interl,interr));//Case 2
}
}
inline void prepare()
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
splayi.creat();
splayv.creat();
positive=0;
n=q=0;
}
int main()
{
freopen("joy.in","r",stdin);
freopen("joy.out","w",stdout);
int operch=0,l=0,r=0;
ll c=0;
for (scanf("%d",&task);task;task--)
{
prepare();
init();
for (;q;q--)
{
scanf("%d",&operch);
if (operch==0)
{
scanf("%d%d%I64d",&l,&r,&c);
if (l!=1) add(l,c);
if (r!=n) add(r+1,-c);
}
else
printf("%I64d %d\n",positive,splayv.mintime(positive));
}
}
return 0;
}