BZOJ1756 小白逛公园
BZOJ1756 小白逛公园
题目描述
在小新家附近有一条“公园路”,路的一边从南到北依次排着 n个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。
一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,
小白只可以选择第 a 个和第 b 个公园之间(包括 a 、 b 两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。
同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。
那么,就请你来帮小白选择公园吧。
输入格式
第一行,两个整数 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 的整数。
输出格式
小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。
Solution
显然的线段树。
每个结点需要维护最大子段和,包含从左端点的最大子段和,包含右端点的最大子段和,然后讨论吧
主要就是pushdown比较麻烦。
#include<bits/stdc++.h> using namespace std; const int MAXN = 500000 + 10; typedef long long ll; inline ll read() { ll f=1,x=0; char ch; do { ch=getchar(); if(ch=='-') f=-1; }while(ch<'0'||ch>'9'); do { x=(x<<3)+(x<<1)+ch-'0'; ch=getchar(); }while(ch>='0'&&ch<='9'); return f*x; } int n,m; int a[MAXN]; struct node { int l,r; int lmax,rmax,sum,ans; inline int mid() { return (l+r)>>1; } };node tree[MAXN*4]; #define lc o<<1 #define rc o<<1|1 inline void pushup(int o) { tree[o].sum=tree[lc].sum+tree[rc].sum; tree[o].lmax=max(tree[lc].lmax,tree[lc].sum+tree[rc].lmax); tree[o].rmax=max(tree[rc].rmax,tree[rc].sum+tree[lc].rmax); tree[o].ans=max(max(tree[lc].ans,tree[rc].ans),tree[lc].rmax+tree[rc].lmax); return; } inline void build(int o,int l,int r) { tree[o].l=l;tree[o].r=r; if(l==r) { tree[o].sum=a[l]; tree[o].lmax=tree[o].rmax=tree[o].ans=a[l]; return; } int mid=tree[o].mid(); build(lc,l,mid); build(rc,mid+1,r); pushup(o); } inline void update(int o,int x,int y) { int l = tree[o].l,r=tree[o].r; if(l==r) { tree[o].sum=y; tree[o].lmax=tree[o].rmax=tree[o].ans=y; //cout<<l<<" "<<tree[o].sum<<endl; return; } int mid=tree[o].mid(); if(x<=mid) update(lc,x,y); else update(rc,x,y); pushup(o); } inline node query(int o,int x,int y) { int l =tree[o].l,r=tree[o].r; if(l>=x&&r<=y) return tree[o]; else { int mid = tree[o].mid(); if(y<=mid) return query(lc,x,y); else if(x>mid) return query(rc,x,y); else { node t = query(lc,x,y); node t1 = query(rc,x,y); node now; now.lmax=max(t.lmax,t.sum+t1.lmax); now.rmax=max(t1.rmax,t1.sum+t.rmax); now.ans=max(max(t.ans,t1.ans),t.rmax+t1.lmax); return now; } } } int main() { n = read();m = read(); for(int i=1;i<=n;i++) a[i]=read(); build(1,1,n); for(int i=1;i<=m;i++) { int k=read(),x=read(),y=read(); if(k==1) { if(x>y) swap(x,y); cout<<query(1,x,y).ans<<endl; } if(k==2) { update(1,x,y); } } }
然后update里脑抽写错一行,调了好久。。。
inline void update(int o,int x,int y) { int l = tree[o].l,r=tree[o].r; if(l==r) { tree[o].sum=y; tree[o].lmax=tree[o].rmax=tree[o].ans=y; //cout<<l<<" "<<tree[o].sum<<endl; return; } int mid=tree[o].mid(); if(x<=mid) build(lc,x,y);//??! else build(rc,x,y);//??! pushup(o); }
我也不知道上面的代码我是怎么打出来的