【BZOJ】 旅行规划-分块

传送门: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;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/80294332