1756: Vijos1083 小白逛公园
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1305 Solved: 429
[ Submit][ Status][ Discuss]
Description
小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。 一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第a个和第b个公园之间(包括a、b两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。 那么,就请你来帮小白选择公园吧。
Input
第一行,两个整数N和M,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。 接下来N行,每行一个整数,依次给出小白 开始时对公园的打分。 接下来M行,每行三个整数。第一个整数K,1或2。K=1表示,小新要带小白出去玩,接下来的两个整数a和b给出了选择公园的范围(1≤a,b≤N);K=2表示,小白改变了对某个公园的打分,接下来的两个整数p和s,表示小白对第p个公园的打分变成了s(1≤p≤N)。 其中,1≤N≤500 000,1≤M≤100 000,所有打分都是绝对值不超过1000的整数。
Output
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
Sample Input
5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3
Sample Output
2
-1
-1
HINT
Source
维护区间和sum,左边的答案lmax,右边的答案rmax,和整个区间的答案ans
那么就这样上传信息。。
inline void pushup(node &ro,node l,node r)
{
ro.sum=l.sum+r.sum;
ro.ans=max(l.ans,r.ans);
ro.ans=max(ro.ans,l.rmax+r.lmax);
ro.lmax=max(l.lmax,l.sum+r.lmax);
ro.rmax=max(r.rmax,r.sum+l.rmax);
}
有一道类似的题目:
传送门
我本来想像那道题一样
记录从左往右取的长度
如果长度为整个区间,那么就可以考虑是否再加上右区间的lmax
后来发现不行
看一组数据吧
3 -1 2 4
我们会发现对于[1,2]这个区间
虽然左区间的lmax取满了
但因为右边的lmax为-1
所以整个[1,2]区间的lmax还是3,长度仅有1
这就使[1,4]的lmax也只有3
而实际上应该是8的
这两题的区别是那道题的ans必须是连续的1
而这题只要连续的sum最大即可
所以局部的最优不是整体的最优。。
#include<cstdio>
#include<cstring>
inline int read()
{
int ans=0,f=1;char t=getchar();
while(t<'0'||t>'9') f=(t=='-'?-1:1),t=getchar();
while(t>='0'&&t<='9') ans=ans*10+t-'0',t=getchar();
return ans*f;
}
#define lson ro<<1
#define rson ro<<1|1
const int N=500007;
struct node
{
int l,r;
int sum,lmax,rmax,ans;
}e[N*4];
inline int max(int a,int b)
{
return a>b?a:b;
}
inline void swap(int &a,int &b)
{
int tmp=a;a=b,b=tmp;
}
inline void pushup(node &ro,node l,node r)
{
ro.sum=l.sum+r.sum;
ro.ans=max(l.ans,r.ans);
ro.ans=max(ro.ans,l.rmax+r.lmax);
ro.lmax=max(l.lmax,l.sum+r.lmax);
ro.rmax=max(r.rmax,r.sum+l.rmax);
}
void build(int ro,int l,int r)
{
e[ro].l=l;e[ro].r=r;
if(l==r)
{
e[ro].sum=e[ro].ans=e[ro].lmax=e[ro].rmax=read();
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);build(rson,mid+1,r);
pushup(e[ro],e[lson],e[rson]);
}
void modify(int ro,int x,int num)
{
if(e[ro].l==e[ro].r)
{
e[ro].sum=e[ro].ans=e[ro].lmax=e[ro].rmax=num;
return;
}
int mid=(e[ro].l+e[ro].r)>>1;
if(x<=mid) modify(lson,x,num);
else modify(rson,x,num);
pushup(e[ro],e[lson],e[rson]);
}
node query(int ro,int l,int r)
{
if(l<=e[ro].l&&e[ro].r<=r) return e[ro];
int mid=(e[ro].l+e[ro].r)>>1;
if(r<=mid) return query(lson,l,r);
else if(l>mid) return query(rson,l,r);
else
{
node ans;
node a=query(lson,l,mid),b=query(rson,mid+1,r);
pushup(ans,a,b);
return ans;
}
}
int main()
{
int n=read(),m=read();
build(1,1,n);
int opt,u,v;
for(int i=1;i<=m;i++)
{
opt=read(),u=read(),v=read();
if(opt==1)
{
if(u>v) swap(u,v);
printf("%d\n",query(1,u,v).ans);
}
else modify(1,u,v);
}
return 0;
}