BZOJ 1756: Vijos1083 小白逛公园  (线段树维护单点修改区间查询最大子段和)

1756: Vijos1083 小白逛公园

Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 1078  Solved: 353 [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

Sample Output

2 -1

题意:中文题面,不多说。

思路:关于维护最大子段和的问题,做法同

hitoj2687题解

但是和上面这道题不同的是,每次询问的是某个区间的最大字段和,而不是整个区间的最大子段和。

我们的做法是,将查询的区间拆成若干个区间,然后按照pushup中的方法合并。

一个技巧是query的时候返回一个结构体,这样会比较好写。

  1/* ***********************************************
  2Author :111qqz
  3Created Time :Fri 16 Sep 2016 03:15:50 AM CST
  4File Name :code/bzoj/1756.cpp
  5************************************************ */
  6#include <cstdio>
  7#include <cstring>
  8#include <iostream>
  9#include <algorithm>
 10#include <vector>
 11#include <queue>
 12#include <set>
 13#include <map>
 14#include <string>
 15#include <cmath>
 16#include <cstdlib>
 17#include <ctime>
 18#define fst first
 19#define sec second
 20#define lson l,m,rt<<1
 21#define rson m+1,r,rt<<1|1
 22#define ms(a,x) memset(a,x,sizeof(a))
 23typedef long long LL;
 24#define pi pair < int ,int >
 25#define MP make_pair
 26using namespace std;
 27const double eps = 1E-8;
 28const int dx4[4]={1,0,0,-1};
 29const int dy4[4]={0,-1,1,0};
 30const int inf = 0x3f3f3f3f;
 31const int N=5E5+7;
 32int n,m;
 33int a[N];
 34struct Tree
 35{
 36    int sum;
 37    int mxl;
 38    int mxr;
 39    int mx;
 40}tree[N<<2];
 41void PushUp(int rt)
 42{
 43    tree[rt].sum = tree[rt<<1].sum+tree[rt<<1|1].sum;
 44    if (tree[rt<<1].mxr>0&&tree[rt<<1|1].mxl>0)
 45	tree[rt].mx = tree[rt<<1].mxr+tree[rt<<1|1].mxl;
 46    else tree[rt].mx = max(tree[rt<<1].mxr,tree[rt<<1|1].mxl);
 47    tree[rt].mx = max(tree[rt].mx,max(tree[rt<<1].mx,tree[rt<<1|1].mx));
 48    tree[rt].mxl=max(tree[rt<<1].mxl,tree[rt<<1].sum+tree[rt<<1|1].mxl);
 49    tree[rt].mxr=max(tree[rt<<1|1].mxr,tree[rt<<1|1].sum+tree[rt<<1].mxr);
 50}
 51void build(int l,int r,int rt)
 52{
 53 //   cout<<"l:"<<l<<" r:"<<r<< " rt:"<<rt<<endl;
 54    if (l==r)
 55    {
 56	int tmp;
 57	scanf("%d",&tmp);
 58//	cout<<"tmp:"<<tmp<<endl;
 59	tree[rt].mx = tree[rt].mxl = tree[rt].mxr = tree[rt].sum = tmp;
 60	return ;
 61    }
 62    int m = (l+r)>>1;
 63    build(lson);
 64    build(rson);
 65    PushUp(rt);
 66}
 67void update( int p,int sc,int l,int r,int rt)
 68{
 69    if (l==r)
 70    {
 71	tree[rt].mx = tree[rt].mxl = tree[rt].mxr = tree[rt].sum = sc;
 72	return ;
 73    }
 74    int m = (l+r)>>1;
 75    if (p<=m) update(p,sc,lson);
 76    else update(p,sc,rson);
 77    PushUp(rt);
 78}
 79Tree query(int L,int R,int l,int r,int rt)
 80{
 81    if (L<=l&&r<=R) return tree[rt];
 82    int m = (l+r)>>1;
 83    if (L<=m&&R>=m+1)
 84    {
 85	Tree root,ltree,rtree;
 86	ltree=query(L,R,lson);
 87	rtree=query(L,R,rson);
 88	root.sum = ltree.sum + rtree.sum;
 89	if (ltree.mxr>0&&rtree.mxl>0)
 90	    root.mx = ltree.mxr + rtree.mxl;
 91	else root.mx = max(ltree.mxr,rtree.mxl);
 92	root.mx = max(root.mx,max(ltree.mx,rtree.mx));
 93	root.mxl = max(ltree.mxl,rtree.mxl+ltree.sum);
 94	root.mxr = max(rtree.mxr,ltree.mxr+rtree.sum);
 95	return root;
 96    }
 97    else
 98    if (L<=m) return query(L,R,lson);
 99    else   return query(L,R,rson);
100}
101int main()
102{
103	#ifndef  ONLINE_JUDGE 
104	freopen("code/in.txt","r",stdin);
105  #endif
106	scanf("%d%d",&n,&m);
107	build(1,n,1);
108	while (m--)
109	{
110	    int opt;
111	    scanf("%d",&opt);
112	    if (opt==1)
113	    {
114		int a,b;
115		scanf("%d%d",&a,&b);
116		if (a>b) swap(a,b);
117		int ans = query(a,b,1,n,1).mx;
118		printf("%d\n",ans);
119	    }else
120	    {
121		int p,x;
122		scanf("%d%d",&p,&x);
123		update(p,x,1,n,1);
124	    }
125	}
126  #ifndef ONLINE_JUDGE  
127  fclose(stdin);
128  #endif
129    return 0;
130}