传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2116
首先这道题第6、7个点数据有问题,差分后的的序列会有0
然后看题
第一问,把原序列差分,差分序列的正数和就是答案
第二问实质上是扩展左区间的右端点和右区间的左端点使得得分下降,负数区间的权值为区间和减区间max,所以我们要维护区间和区间max,负数区间和支持前k小和的平衡树
线段树+set+Treap解决,修改的时候需要分4类讨论……正->正 正->负 负->正 负->负
Code(除了第7个点其他都能过):
#include<bits/stdc++.h>
#define fst first
#define sec second
using namespace std;
const int maxn=1e5+5;
typedef pair<int,int> par;
typedef long long LL;
int n,q,a[maxn],b[maxn];
LL ans1;
int getint(){
int res=0,f=1;char c=getchar();
while(!isdigit(c))f=f==-1||c=='-'?-1:1,c=getchar();
while(isdigit(c))res=res*10+c-'0',c=getchar();
return res*f;
}
set<par>Neg;
struct Treap{
struct node{
LL val;LL sum;int key;
int size,s;
node *c[2];
node(int _val=0,node *C=0){
val=sum=_val;size=s=1;
c[0]=c[1]=C;key=rand();
}
void rz(){
size=c[0]->size+s+c[1]->size;
sum=c[0]->sum+(LL)val*s+c[1]->sum;
}
}*null,*root;
void rot(node *&t,bool d){
node *p=t->c[d];t->c[d]=p->c[!d];
p->c[!d]=t;t->rz();p->rz();t=p;
}
void insert(node *&t,LL x){
if(t==null){t=new node(x,null);return;}
if(t->val==x){t->size++;t->s++;t->sum+=x;return;}
insert(t->c[t->val<x],x);
if(t->c[t->val<x]->key<t->key)rot(t,t->val<x);
else t->rz();
}
void del(node *&t,LL x){
if(t==null)return;
if(t->val==x){
if(t->s>1){t->s--;t->size--;t->sum-=t->val;return;}
bool d=t->c[0]->key>t->c[1]->key;
if(t->c[d]==null){delete t;t=null;return;}
rot(t,d);del(t->c[!d],x);
}else del(t->c[t->val<x],x);t->rz();
}
void insert(LL x){insert(root,x);}
int Q(LL x){
if(root->sum+x>0)return -1;
node *t=root;int ans=0;
while(t!=null){
if(t->c[0]->sum+x<=0)t=t->c[0];
else{
if(t->c[0]->sum+(LL)t->val*t->s+x<=0){
return ans+t->c[0]->size+ceil((double)(t->c[0]->sum+x)/-t->val-1e-10);
}else ans+=t->c[0]->size+t->s,x+=t->c[0]->sum+(LL)t->val*t->s,t=t->c[1];
}
}return ans;
}
void del(LL x){del(root,x);}
void erase(node *t){
if(t->c[0]!=null)erase(t->c[0]);
if(t->c[1]!=null)erase(t->c[1]);
delete t;
}
void clear(){
if(root)erase(root);
null=new node();
null->size=null->s=0;null->key=INT_MAX;
null->c[0]=null->c[1]=null;
root=null;
}
void deb(node *t){
if(t==null)return;
printf("val:%d sum:%d size:%d s:%d\n",t->val,t->sum,t->size,t->s);
if(t->c[0]!=null)deb(t->c[0]);
if(t->c[1]!=null)deb(t->c[1]);
}
void deb(){deb(root);};
}T;
struct seg{
struct node{
LL sum;int mx;
node(){sum=0;mx=INT_MIN;}
node operator+(const node &rs){
node c;c.sum=sum+rs.sum;
c.mx=max(mx,rs.mx);return c;
}
}t[maxn<<2];
#define lson i<<1,l,(l+r)/2
#define rson i<<1|1,(l+r)/2+1,r
#define ls i<<1
#define rs i<<1|1
void clear(){for(int i=0;i<(maxn<<2);i++)t[i].sum=0,t[i].mx=INT_MIN;}
void build(int i,int l,int r){
if(l==r){t[i].sum=t[i].mx=a[l];return;}
build(lson);build(rson);t[i]=t[ls]+t[rs];
}
void add(int i,int l,int r,int ps,int c){
if(l==r){t[i].mx+=c;t[i].sum+=c;return;}
if(ps<=(l+r)/2)add(lson,ps,c);
else add(rson,ps,c);t[i]=t[ls]+t[rs];
}
int Qmax(int i,int l,int r,int l0,int r0){
if(l0<=l&&r0>=r)return t[i].mx;
int ans=INT_MIN;
if(l0<=(l+r)/2)ans=max(ans,Qmax(lson,l0,r0));
if(r0>(l+r)/2)ans=max(ans,Qmax(rson,l0,r0));
return ans;
}
LL Qsum(int i,int l,int r,int l0,int r0){
if(l0<=l&&r0>=r)return t[i].sum;
LL ans=0;
if(l0<=(l+r)/2)ans+=Qsum(lson,l0,r0);
if(r0>(l+r)/2)ans+=Qsum(rson,l0,r0);
return ans;
}
int Qmax(int l,int r){return Qmax(1,1,n-1,l,r);}
int Qsum(int l,int r){return Qsum(1,1,n-1,l,r);}
void Add(int ps,int c){add(1,1,n-1,ps,c);}
}sgt;
int Qw(par pi){return sgt.Qsum(pi.fst,pi.sec)-sgt.Qmax(pi.fst,pi.sec);}
void del(par pi){if(pi.fst!=1&&pi.sec!=n-1)T.del(Qw(pi));}
void insert(par pi){if(pi.fst!=1&&pi.sec!=n-1)T.insert(Qw(pi));}
void Add(int ps,int c){
if(a[ps]<0){
if(a[ps]+c<0){
set<par>::iterator it=--Neg.upper_bound(par(ps,n+1));
if(it->fst!=1&&it->sec!=n-1){del(*it);sgt.Add(ps,c);insert(*it);}
else sgt.Add(ps,c);
}else{
set<par>::iterator it=--Neg.upper_bound(par(ps,n+1));
par p=*it;Neg.erase(p);del(p);sgt.Add(ps,c);
if(p.fst<=ps-1){Neg.insert(par(p.fst,ps-1));
insert(par(p.fst,ps-1));}
if(ps+1<=p.sec)Neg.insert(par(ps+1,p.sec)),insert(par(ps+1,p.sec));
}
}else{
if(a[ps]+c<0){
if(ps>1&&a[ps-1]<0&&ps+1<n&&a[ps+1]<0){
set<par>::iterator nxt=Neg.upper_bound(par(ps,n));
set<par>::iterator pre=--nxt;nxt++;
par p=par(pre->fst,nxt->sec);
del(*pre);Neg.erase(*pre);
del(*nxt);Neg.erase(*nxt);
sgt.Add(ps,c);
insert(p);Neg.insert(p);
}else
if(ps>1&&a[ps-1]<0){
set<par>::iterator nxt=Neg.upper_bound(par(ps,n));
set<par>::iterator pre=--nxt;nxt++;
par p=par(pre->fst,ps);
del(*pre);Neg.erase(*pre);sgt.Add(ps,c);
insert(p);Neg.insert(p);
}else
if(ps+1<n&&a[ps+1]<0){
set<par>::iterator nxt=Neg.upper_bound(par(ps,n));
par p=par(ps,nxt->sec);
del(*nxt);Neg.erase(*nxt);sgt.Add(ps,c);
insert(p);Neg.insert(p);
}else sgt.Add(ps,c),Neg.insert(par(ps,ps)),insert(par(ps,ps));
}else sgt.Add(ps,c);
}
}
void solve(){
ans1=0;sgt.clear();T.clear();Neg.clear();
n=getint();q=getint();
for(int i=1;i<=n;i++)b[i]=getint();
for(int i=1;i<n;i++)a[i]=b[i+1]-b[i];
sgt.build(1,1,n-1);
int st=n;
for(int i=1;i<n;i++){
ans1+=a[i]*(a[i]>0);
if(a[i]>0){
if(st<=i-1){
Neg.insert(par(st,i-1));
insert(par(st,i-1));
st=n;
}
}else if(st==n)st=i;
}
if(st<=n-1)Neg.insert(par(st,n-1)),
insert(par(st,n-1));
while(q--){
int op=getint();
if(op==1){
printf("%I64d %d\n",ans1,T.Q(ans1));
}else{
int l=getint(),r=getint(),c=getint();
if(l>1)Add(l-1,c),ans1-=a[l-1]*(a[l-1]>0),a[l-1]+=c,ans1+=a[l-1]*(a[l-1]>0);//,assert(a[l-1]!=0);
if(r<n)Add(r,-c),ans1-=a[r]*(a[r]>0),a[r]-=c,ans1+=a[r]*(a[r]>0);//,assert(a[r]!=0);
}
}
}
int main(){
int T;scanf("%d",&T);
while(T--)solve();
return 0;
}