Bzoj 1756: Vijos1083 小白逛公园 线段树
1756: Vijos1083 小白逛公园
Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1021 Solved: 326
[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
题解:
线段树维护。
记得查询时可能覆盖两个区间,所以要传下去结构体。
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define MAXN 500010 4 struct node 5 { 6 int left,right,lx,rx,mx,sum; 7 }tree[5*MAXN]; 8 int a[MAXN]; 9 int read() 10 { 11 int s=0,fh=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();} 14 return s*fh; 15 } 16 void Build(int k,int l,int r) 17 { 18 tree[k].left=l;tree[k].right=r;tree[k].sum=0; 19 if(l==r)return; 20 int mid=(l+r)/2; 21 Build(k*2,l,mid);Build(k*2+1,mid+1,r); 22 } 23 void Pushup(int k) 24 { 25 tree[k].sum=tree[k*2].sum+tree[k*2+1].sum; 26 tree[k].mx=max(tree[k*2].mx,tree[k*2+1].mx); 27 tree[k].mx=max(tree[k].mx,tree[k*2].rx+tree[k*2+1].lx); 28 tree[k].lx=max(tree[k*2].lx,tree[k*2].sum+tree[k*2+1].lx); 29 tree[k].rx=max(tree[k*2+1].rx,tree[k*2+1].sum+tree[k*2].rx); 30 } 31 void Change(int k,int lr,int C) 32 { 33 if(tree[k].left==tree[k].right){tree[k].sum=tree[k].lx=tree[k].rx=tree[k].mx=C;return;} 34 int mid=(tree[k].left+tree[k].right)/2; 35 if(lr<=mid)Change(k*2,lr,C); 36 else Change(k*2+1,lr,C); 37 Pushup(k); 38 } 39 node Query_max(int k,int l,int r) 40 { 41 if(l<=tree[k].left&&tree[k].right<=r)return tree[k]; 42 int mid=(tree[k].left+tree[k].right)/2; 43 if(r<=mid)return Query_max(k*2,l,r); 44 else if(l>mid)return Query_max(k*2+1,l,r); 45 else 46 { 47 node ll,rr,nn; 48 ll=Query_max(k*2,l,mid);rr=Query_max(k*2+1,mid+1,r); 49 nn.sum=ll.sum+rr.sum; 50 nn.mx=max(ll.mx,rr.mx); 51 nn.mx=max(nn.mx,ll.rx+rr.lx); 52 nn.lx=max(ll.lx,ll.sum+rr.lx); 53 nn.rx=max(rr.rx,rr.sum+ll.rx); 54 return nn; 55 } 56 } 57 int main() 58 { 59 int n,m,i,K,A,B; 60 n=read();m=read(); 61 for(i=1;i<=n;i++)a[i]=read(); 62 Build(1,1,n); 63 for(i=1;i<=n;i++)Change(1,i,a[i]); 64 for(i=1;i<=m;i++) 65 { 66 K=read();A=read();B=read(); 67 if(A>B&&K==1)swap(A,B); 68 if(K==1) 69 { 70 node nn; 71 nn=Query_max(1,A,B); 72 printf("%d\n",nn.mx); 73 } 74 else Change(1,A,B); 75 } 76 fclose(stdin); 77 fclose(stdout); 78 return 0; 79 }