#KTT#洛谷 5073 [Ynoi Easy Round 2015] 世上最幸福的女孩
题目
支持全局加和查询区间最大子段和
分析
虽然全局加可能加一个负数,但是可以离线通过调换查询顺序做到一直加一个正数。
那么就可以用 KTT 来做,最大子段和在线段树上需要维护左右端点为一端的最大前后缀以及答案。
那么这些都可以被表示成一次函数 \(S_0x+S_1\)的形式,自变量为当前添加的变化量,
这题有点卡常所以全局加可以减小参数来优化常数。
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
typedef long long lll; const lll inf=1e18;
const int N=300011; lll a[N],n,Q,ans[N<<1];
struct rec{lll sum,lmax,rmax,w;}q[N<<1];
struct Segment_Tree{
rec K[N<<2],B[N<<2]; lll bound[N<<2],lazy[N<<2];
void pmax(lll k1,lll b1,lll k2,lll b2,lll &k,lll &b,lll &bound){
if (b1<b2||(b1==b2&&k1<k2)) swap(k1,k2),swap(b1,b2);
k=k1,b=b1;
if (k1<k2) bound=min(bound,(b1-b2)/(k2-k1));
}
rec pup(rec x,rec y){
return (rec){x.sum+y.sum,max(x.lmax,x.sum+y.lmax),max(y.rmax,x.rmax+y.sum),max(max(x.w,y.w),x.rmax+y.lmax)};
}
void pup(int k){
K[k].sum=K[k<<1].sum+K[k<<1|1].sum,B[k].sum=B[k<<1].sum+B[k<<1|1].sum,bound[k]=min(bound[k<<1],bound[k<<1|1]);
pmax(K[k<<1].lmax,B[k<<1].lmax,K[k<<1].sum+K[k<<1|1].lmax,B[k<<1].sum+B[k<<1|1].lmax,K[k].lmax,B[k].lmax,bound[k]);
pmax(K[k<<1|1].rmax,B[k<<1|1].rmax,K[k<<1].rmax+K[k<<1|1].sum,B[k<<1].rmax+B[k<<1|1].sum,K[k].rmax,B[k].rmax,bound[k]);
pmax(K[k<<1].w,B[k<<1].w,K[k<<1|1].w,B[k<<1|1].w,K[k].w,B[k].w,bound[k]);
pmax(K[k].w,B[k].w,K[k<<1].rmax+K[k<<1|1].lmax,B[k<<1].rmax+B[k<<1|1].lmax,K[k].w,B[k].w,bound[k]);
}
void ptag(int k,lll z){
B[k].sum+=K[k].sum*z,B[k].lmax+=K[k].lmax*z,
B[k].rmax+=K[k].rmax*z,B[k].w+=K[k].w*z,lazy[k]+=z;
if (bound[k]!=inf) bound[k]-=z;
}
void build(int k,int l,int r){
lazy[k]=0;
if (l==r){
K[k]=(rec){1,1,1,1},B[k]=(rec){a[l],a[l],a[l],a[l]},bound[k]=inf;
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
pup(k);
}
void rebuild(int k,int l,int r,lll z){
if (z<=bound[k]){
ptag(k,z);
return;
}
int mid=(l+r)>>1;
if (lazy[k]){
ptag(k<<1,lazy[k]);
ptag(k<<1|1,lazy[k]);
lazy[k]=0;
}
rebuild(k<<1,l,mid,z);
rebuild(k<<1|1,mid+1,r,z);
pup(k);
}
rec query(int k,int l,int r,int x,int y){
if (l==x&&r==y) return B[k];
int mid=(l+r)>>1;
if (lazy[k]){
ptag(k<<1,lazy[k]);
ptag(k<<1|1,lazy[k]);
lazy[k]=0;
}
if (y<=mid) return query(k<<1,l,mid,x,y);
else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
else return pup(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
}
}Tre;
bool cmp(rec x,rec y){return x.w<y.w;}
int iut(){
int ans=0,f=1; char c=getchar();
while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans*f;
}
void print(lll ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int main(){
n=iut(),Q=iut();
for (int i=1;i<=n;++i) a[i]=iut();
lll now=0;
for (int i=1;i<=Q;++i){
int opt=iut(),x=iut();
if (opt==1) now+=x,--i,--Q;
else q[i]=(rec){i,x,iut(),now};
}
sort(q+1,q+1+Q,cmp),q[0].w=q[1].w;
for (int i=1;i<=n;++i) a[i]+=q[0].w;
Tre.build(1,1,n);
for (int l=1,r;l<=Q;l=r+1){
for (r=l;r<=Q&&q[r].w==q[l].w;++r); --r;
if (q[l-1].w!=q[l].w) Tre.rebuild(1,1,n,q[l].w-q[l-1].w);
for (int i=l;i<=r;++i) ans[q[i].sum]=Tre.query(1,1,n,q[i].lmax,q[i].rmax).w;
}
for (int i=1;i<=Q;++i) print(max(0ll,ans[i])),putchar(10);
return 0;
}

浙公网安备 33010602011771号