传送门:bzoj2388
题解
做这道题时,本蒟蒻很心碎,因为百般debug都WA。
最后也不知道怎么就过了??
单纯分块。
代码
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#define db double
using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll INF=1e15;
ll ini[N],ad[N],tag[N],dif[N],ans;
int st[350],ed[350],sta[350],con[350][350];
int nt[350],n,m,opt,x,y,k,top;
int pos[N],mx[N],block,cnt,l,r,lim;
inline int rd()
{
char ch=getchar();int x=0,f=1;
while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return x*f;
}
inline ll max(ll x,ll y){return x>y?x:y;}
inline int min(int x,int y){return x>y?y:x;}
inline db slop(int x,int y){return (db)(ini[x]-ini[y])/(db)(x-y);}
inline ll cal(int x)
{if(x==0 || x==n+1) return -INF;return (ini[x]+dif[pos[x]]*(x-st[pos[x]])+tag[pos[x]]+ad[pos[x]]);}
inline void build(int x)
{
sta[(top=1)]=st[x];
for(int i=st[x]+1;i<=ed[x];i++){
while(top>=2 && slop(sta[top],sta[top-1])<slop(sta[top-1],i)) top--;
sta[++top]=i;
}
sta[0]=0;sta[top+1]=n+1;nt[x]=top;
for(int i=0;i<=top+1;i++) con[x][i]=sta[i];
}
inline void pushdown(int x)
{
ll ret=tag[x];
for(int i=st[x];i<=ed[x];i++){ini[i]+=(ret+ad[x]);ret+=dif[x];}
tag[x]=ad[x]=dif[x]=0;
}
inline void change(int x,int y,int k)
{
ll ret=k;
l=pos[x],r=pos[y];lim=min(y,ed[l]);pushdown(l);
for(int i=x;i<=lim;i++) {ini[i]+=ret;ret+=k;}build(l);
pushdown(r);ret=k*(st[r]-x+1);
if(l!=r) for(int i=st[r];i<=y;i++) {ini[i]+=ret;ret+=k;}
ret=k*(st[l+1]-x+1);
for(int i=l+1;i<r;i++) {tag[i]+=ret;dif[i]+=k;ret+=block*k;}
ret=k*(y-x+1);
for(int i=y+1;i<=ed[r];i++) ini[i]+=ret;build(r);
for(int i=r+1;i<=cnt;i++) ad[i]+=ret;
}
inline ll ask(int x)
{
int L=1,R=nt[x];ll a,b,c;
while(L<=R){
int mid=(L+R)>>1;
a=cal(con[x][mid-1]),b=cal(con[x][mid]),c=cal(con[x][mid+1]);
if(a<b && b<c) L=mid+1;
else if(a>b && b>c) R=mid-1;
else return b;
}
}
inline void get(int x,int y)
{
l=pos[x],r=pos[y];lim=min(y,ed[l]);ans=-INF;
for(int i=x;i<=lim;i++) ans=max(ans,cal(i));
if(l!=r){for(int i=st[r];i<=y;i++) ans=max(ans,cal(i));}
for(int i=l+1;i<r;i++) ans=max(ans,ask(i));
printf("%lld\n",ans);
}
int main(){
n=rd();block=(int)sqrt(n);cnt=block;
for(int i=1;i<=n;i++) ini[i]=rd()+ini[i-1],pos[i]=(i-1)/block+1;
ini[0]=ini[n+1]=-INF;cnt=n/block;
if(n%block) cnt++;
for(int i=1;i<=cnt;i++) st[i]=block*(i-1)+1,ed[i]=min(n,block*i);
for(int i=1;i<=cnt;i++) build(i);
m=rd();
while(m--){
opt=rd();x=rd();y=rd();
if(!opt) change(x,y,rd());
else get(x,y);
}
return 0;
}