1. 程式人生 > >vijos 1083 小白逛公園

vijos 1083 小白逛公園

img sum 最大 %d using syn scan ide pen

描述

小新經常陪小白去公園玩,也就是所謂的遛狗啦…在小新家附近有一條“公園路”,路的一邊從南到北依次排著n個公園,小白早就看花了眼,自己也不清楚該去哪些公園玩了。

一開始,小白就根據公園的風景給每個公園打了分-.-。小新為了省事,每次遛狗的時候都會事先規定一個範圍,小白只可以選擇第a個和第b個公園之間(包括a、b兩個公園)選擇**連續**的一些公園玩。小白當然希望選出的公園的分數總和盡量高咯。同時,由於一些公園的景觀會有所改變,所以,小白的打分也可能會有一些變化。

那麽,就請你來幫小白選擇公園吧。

格式

輸入格式

第一行,兩個整數N和M,分別表示表示公園的數量和操作(遛狗或者改變打分)總數。

接下來N行,每行一個整數,依次給出小白 開始時對公園的打分。

接下來M行,每行三個整數。第一個整數K,1或2。K=1表示,小新要帶小白出去玩,接下來的兩個整數a和b給出了選擇公園的範圍(1≤a,b≤N, a可以大於b!);K=2表示,小白改變了對某個公園的打分,接下來的兩個整數p和s,表示小白對第p個公園的打分變成了s(1≤p≤N)。

其中,1≤N≤500 000,1≤M≤100 000,所有打分都是絕對值不超過1000的整數。

輸出格式

小白每出去玩一次,都對應輸出一行,只包含一個整數,表示小白可以選出的公園得分和的最大值。

樣例1

樣例輸入1

5 3
1 2 -3 4 5
1 2 3
2 2 -1
1 2 3

Copy

樣例輸出1

2
-1
Copy

限制

各個測試點2s

--------------

解:線段樹;

e數組維護lsum,rsum,msum,sum;

難在query函數,簡單情況大家都懂,難的解決方法是:

開三個結構體:tl,tr,tt;

tl:左邊對應的情況;

tr:同上;

tt:即為答案;

技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using std::max;
using std::swap; 
const int N=500010;
struct node
{
    int l,r,lsum,rsum,msum,sum;
}e[N
<<2]; #define ls ro<<1 #define rs ro<<1|1 inline void pushup(int ro) { e[ro].sum=e[ls].sum+e[rs].sum; e[ro].lsum=max(e[ls].lsum,e[ls].sum+e[rs].lsum); e[ro].rsum=max(e[rs].rsum,e[rs].sum+e[ls].rsum); e[ro].msum=max(max(e[ls].msum,e[rs].msum),e[ls].rsum+e[rs].lsum); } void build(int ro,int l,int r) { e[ro].l=l,e[ro].r=r; if(l==r) { int x; scanf("%d",&x); e[ro].lsum=e[ro].rsum=e[ro].msum=e[ro].sum=x; return; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); pushup(ro); } void change(int ro,int x,int p) { if(e[ro].l==e[ro].r) { if(e[ro].l==x) e[ro].lsum=e[ro].rsum=e[ro].msum=e[ro].sum=p; return; } int mid=(e[ro].l+e[ro].r)>>1; if(x<=mid) change(ls,x,p); else change(rs,x,p); pushup(ro); } node query(int ro,int l,int r) { node tl,tr,tt; if(e[ro].l==l&&e[ro].r==r) return e[ro]; int mid=(e[ro].l+e[ro].r)>>1; if(r<=mid) return query(ls,l,r); else if(mid<l) return query(rs,l,r); else { tl=query(ls,l,mid); tr=query(rs,mid+1,r); tt.msum=max(max(tl.msum,tr.msum),tl.rsum+tr.lsum); tt.lsum=max(tl.lsum,tl.sum+tr.lsum); tt.rsum=max(tr.rsum,tr.sum+tl.rsum); return tt; } } int main() { int n,m; scanf("%d %d",&n,&m); build(1,1,n); // for(int i=1;i<=20;i++) // printf("std:: %d %d %d %d %d %d\n",e[i].l,e[i].r,e[i].lsum,e[i].rsum,e[i].msum,e[i].sum); int dp,l,r; for(int i=1;i<=m;i++) { scanf("%d %d %d",&dp,&l,&r); if(dp==1) { if(l>r) swap(l,r); node ans=query(1,l,r); printf("%d\n",ans.msum); } else { change(1,l,r); // for(int i=1;i<=20;i++) // printf("std:: %d %d %d %d %d %d\n",e[i].l,e[i].r,e[i].lsum,e[i].rsum,e[i].msum,e[i].sum); } } return 0; }
vijos 1083

vijos 1083 小白逛公園