描述
小新经常陪小白去公园玩,也就是所谓的遛狗啦…在小新家附近有一条“公园路”,路的一边从南到北依次排着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
样例输出1
2
-1
限制
各个测试点2s
这是一道线段树的题,和一般不同的是这道题求一个区间内连续几个的最大值,这个就要多定义一个从左边开始和从右边开始的连续最大值lmax和rmax
在简单的提醒后,很快的把题的大部分打完了,最后卡在询问环节,还是多亏了大佬Ztraveler的帮助点醒了我
我就简单的提一下我卡住的地方
当我们要求出的L和R区间的LR在mid的同一侧就是一个简单的询问操作,但是当L和R分居mid的两侧时,就要稍作处理
我和那位大佬的方法是新开三个结构体,ly,ry,yy,分别是L到mid,mid+1到R和L到R,这样下来就可以就出L到R中的答案了
然后再提醒一点小细节,就是查询时a可能大于b也可能小于b
说的可能不是很清晰,还是看代码分析吧
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 #include<iostream> 6 #include<cstdlib> 7 #define maxn 500005 8 #define lson pos<<1 9 #define rson pos<<1|1 10 using namespace std; 11 12 struct node{ 13 int sum,l,r,lmax,rmax,maxx; 14 }e[maxn*4]; 15 16 int a[maxn],n,m; 17 18 void pushup(int pos)//更新操作 19 { 20 e[pos].sum=e[lson].sum+e[rson].sum; 21 e[pos].lmax=max(e[lson].lmax,e[lson].sum+e[rson].lmax); 22 e[pos].rmax=max(e[rson].rmax,e[rson].sum+e[lson].rmax); 23 e[pos].maxx=max(max(max(e[lson].lmax,e[rson].rmax),e[lson].rmax+e[rson].lmax),max(e[lson].maxx,e[rson].maxx)); 24 } 25 26 void build(int l,int r,int pos) 27 { 28 e[pos].l=l;e[pos].r=r; 29 if(l==r) 30 { 31 e[pos].lmax=a[l]; 32 e[pos].rmax=a[l]; 33 e[pos].maxx=a[l]; 34 e[pos].sum =a[l]; 35 }else{ 36 int mid=(l+r)>>1; 37 build(l,mid,lson); 38 build(mid+1,r,rson); 39 pushup(pos); 40 } 41 } 42 43 node query(int l,int r,int pos) 44 { 45 if(e[pos].l==l&&e[pos].r==r) 46 { 47 return e[pos]; 48 }else{ 49 int mid=(e[pos].l+e[pos].r)>>1; 50 if(mid>=r){ 51 return query(l,r,pos<<1); 52 }else{ 53 if(mid<l)return query(l,r,pos<<1|1); 54 else {//当要找的LR分居mid两侧 55 node ly=query(l,mid,lson); 56 node ry=query(mid+1,r,rson); 57 node yy; 58 yy.sum=ly.sum+ry.sum; 59 yy.lmax=max(ly.lmax,ly.sum+ry.lmax); 60 yy.rmax=max(ry.rmax,ry.sum+ly.rmax); 61 yy.maxx=max(max(max(ly.lmax,ry.rmax),ly.rmax+ry.lmax),max(ly.maxx,ry.maxx)); 62 return yy; 63 } 64 } 65 } 66 } 67 68 void change(int l,int r,int k,int x,int pos) 69 { 70 if(l==k&&r==k) 71 { 72 e[pos].lmax=e[pos].rmax=e[pos].maxx=e[pos].sum=x; 73 }else{ 74 int mid=(l+r)>>1; 75 if(k<=mid) 76 { 77 change(l,mid,k,x,pos<<1); 78 pushup(pos); 79 80 }else{ 81 change(mid+1,r,k,x,pos<<1|1); 82 pushup(pos); 83 } 84 } 85 } 86 87 int main() 88 { 89 scanf("%d%d",&n,&m); 90 for(int i=1;i<=n;i++) 91 { 92 scanf("%d",&a[i]); 93 } 94 build(1,n,1); 95 for(int i=1;i<=m;i++) 96 { 97 int q; 98 scanf("%d",&q); 99 if(q==1) 100 { 101 int a,b; 102 scanf("%d%d",&a,&b); 103 if(a>b)printf("%d ",query(b,a,1).maxx); 104 else printf("%d ",query(a,b,1).maxx);//不要被这个小细节坑了 105 }else{ 106 int a,b; 107 scanf("%d%d",&a,&b); 108 change(1,n,a,b,1); 109 } 110 } 111 }
做完这题整个人都不好了,感觉这点细节都看不到,我的oi之路艰难啊!!!
ps:代码写的比较稀疏,看起来很多,其实不难的