title
Description
\(OIVillage\) 是一个风景秀美的乡村,为了更好的利用当地的旅游资源,吸引游客,推动经济发展,\(xkszltl\) 决定修建了一条铁路将当地 \(n\) 个最著名的经典连接起来,让游客可以通过火车从铁路起点(1号景点)出发,依次游览每个景区。为了更好的评价这条铁路,\(xkszltl\) 为每一个景区都哦赋予了一个美观度,而一条旅行路径的价值就是它所经过的景区的美观度之和。不过,随着天气与季节的变化,某些景点的美观度也会发生变化。
\(xkszltl\) 希望为每位旅客提供最佳的旅行指导,但是由于游客的时间有限,不一定能游览全部景区,然而他们也不希望旅途过于短暂,所以每个游客都希望能在某一个区间内的车站结束旅程,而 \(xkszltl\) 的任务就是为他们选择一个终点使得旅行线路的价值最大。可是当地的景点与前来观光的旅客实在是太多了,\(xkszltl\) 无法及时完成任务,于是找到了准备虐杀 \(NOI2011\) 的你,希望你能帮助他完成这个艰巨的任务。
Input
第一行给出一个整数 \(n\) ,接下来一行给出 \(n\) 的景区的初始美观度。
第三行给出一个整数 \(m\) ,接下来 \(m\) 行每行为一条指令:
0 x y k
:表示将 \(x\) 到 \(y\) 这段铁路边上的景区的美观度加上 \(k\) ;1 x y
:表示有一名旅客想要在 \(x\) 到 \(y\) 这段(含 \(x\) 与 \(y\) )中的某一站下车,你需要告诉他最大的旅行价值。
Output
对于每个询问,输出一个整数表示最大的旅行价值。
Sample Input
5
1 8 -8 3 -7
3
1 1 5
0 1 3 6
1 2 4
Sample Output
9
22
HINT
Data Limit:
对于 \(20\%\) 的数据,\(n,m\leqslant 3000\);
对于 \(40\%\) 的数据,\(n,m\leqslant 30000\);
对于 \(50\%\) 的数据,\(n,m\leqslant 50000\);
另外 \(20\%\) 的数据,\(n,m\leqslant 100000\),修改操作 \(\leqslant 20\) ;
对于 \(100\%\) 的数据,\(n,m\leqslant 100000\) 。
analysis
这个关于分块的写法,参考 hzwer :
此题可以分块。
对于一块内维护一个凸壳,查询每一块内可以二分。
修改头尾暴力重构,如果将一整块加上一个值,那么最优的点是不会变的,因为相当于将每两点间的斜率加上一个定值。
我的一点点想法,我到现在还是认为 \(BIT\) 可以写这道题,毕竟维护凸包的操作我已经会写了,下面就是得想想怎么样把 \(BIT\) 实现一下,可能会咕掉。
code
#include<bits/stdc++.h>
typedef long long ll;
const int maxn=1e5+10,maxm=350;
const ll INF=1ll<<50;
namespace IO
{
char buf[1<<15],*fs,*ft;
inline char getc() { return (ft==fs&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),ft==fs))?0:*fs++; }
template<typename T>inline void read(T &x)
{
x=0;
T f=1, ch=getchar();
while (!isdigit(ch) && ch^'-') ch=getchar();
if (ch=='-') f=-1, ch=getchar();
while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48), ch=getchar();
x*=f;
}
char Out[1<<24],*fe=Out;
inline void flush() { fwrite(Out,1,fe-Out,stdout); fe=Out; }
template<typename T>inline void write(T x,char str)
{
if (!x) *fe++=48;
if (x<0) *fe++='-', x=-x;
T num=0, ch[20];
while (x) ch[++num]=x%10+48, x/=10;
while (num) *fe++=ch[num--];
*fe++=str;
}
}
using IO::read;
using IO::write;
template<typename T>inline bool chkMin(T &a,const T &b) { return a>b ? (a=b, true) : false; }
template<typename T>inline bool chkMax(T &a,const T &b) { return a<b ? (a=b, true) : false; }
template<typename T>inline T min(T a,T b) { return a<b ? a : b; }
template<typename T>inline T max(T a,T b) { return a>b ? a : b; }
ll h[maxn],fir[maxm],dif[maxm],add[maxm];//首项、公差
inline double slope(int x,int y)
{
return (double)(h[y]-h[x])/(y-x);
}
int bel[maxn],n;
int st[maxm],ed[maxm],num[maxn];
inline ll cal(int x)
{
if (!x || x==n+1) return -INF;
int t=bel[x];
return h[x]+fir[t]+dif[t]*(x-st[t])+add[t];
}
int Stack[maxm],top;
int con[maxm][maxm];//凸包
inline void build(int x)
{
top=0;
Stack[++top]=st[x];
for (int i=st[x]+1; i<=ed[x]; ++i)
{
while (top>1 && slope(Stack[top-1],Stack[top])<slope(Stack[top-1],i)) --top;
Stack[++top]=i;
}
Stack[0]=0, Stack[top+1]=n+1;
num[x]=top;
for (int i=0; i<=top+1; ++i) con[x][i]=Stack[i];
}
inline void pushdown(int x)
{
ll tmp=fir[x];
for (int i=st[x]; i<=ed[x]; ++i) h[i]+=tmp, tmp+=dif[x], h[i]+=add[x];
fir[x]=dif[x]=add[x]=0;
}
inline ll ask(int x)
{
int l=1, r=num[x];
ll h1, h2, h3;
while (l<=r)
{
int mid=(l+r)>>1;
h1=cal(con[x][mid-1]), h2=cal(con[x][mid]), h3=cal(con[x][mid+1]);
if (h1<h2 && h2<h3) l=mid+1;
else if (h1>h2 && h2>h3) r=mid-1;
else return h2;
}
}
int main()
{
read(n);
for (int i=1,x; i<=n; ++i) read(x), h[i]=h[i-1]+x;
h[0]=h[n+1]=-INF;
int block=(int)sqrt(n), cnt=0;
if (n%block) cnt=n/block+1;
else cnt=n/block;
for (int i=1; i<=n; ++i) bel[i]=(i-1)/block+1;
for (int i=1; i<=cnt; ++i) st[i]=(i-1)*block+1, ed[i]=min(n,i*block);
for (int i=1; i<=cnt; ++i) build(i);
int m;read(m);
ll k,ans=0; int l,r;
for (int i=1,opt,x,y; i<=m; ++i)
{
read(opt);read(x);read(y);
if (!opt)
{
read(k);
l=bel[x], r=bel[y];
ll tmp=k*(st[l+1]-x+1);
for (int i=l+1; i<=r-1; ++i) fir[i]+=tmp, dif[i]+=k, tmp+=block*k;
pushdown(l);
tmp=k;
for (int i=x; i<=min(y,ed[l]); ++i) h[i]+=tmp, tmp+=k;
build(l);
pushdown(r);
if (l^r)
{
tmp=k*(st[r]-x+1);
for (int i=st[r]; i<=y; ++i) h[i]+=tmp, tmp+=k;
}
tmp=k*(y-x+1);
for (int i=y+1; i<=ed[r]; ++i) h[i]+=tmp;
build(r);
for (int i=r+1; i<=cnt; ++i) add[i]+=tmp;
}
else
{
l=bel[x], r=bel[y];
ans=-INF;
for (int i=l+1; i<r; ++i) chkMax(ans,ask(i));
for (int i=x; i<=min(y,ed[l]); ++i) chkMax(ans,cal(i));
if (l^r)
{
for (int i=st[r]; i<=y; ++i) chkMax(ans,cal(i));
}
write(ans,'\n');
}
}
IO::flush();
return 0;
}