你能回答这些问题吗 (线段树)

Posted spring-onion

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你能回答这些问题吗 (线段树)相关的知识,希望对你有一定的参考价值。

题目:

给定长度为N的数列A,以及M条指令,每条指令可能是以下两种之一:

1、“1 x y”,查询区间 [x,y] 中的最大连续子段和,即 技术图片

 

2、“2 x y”,把 A[x] 改成 y。

对于每个查询指令,输出一个整数表示答案。

输入格式

第一行两个整数N,M。

第二行N个整数A[i]。

接下来M行每行3个整数k,x,y,k=1表示查询(此时如果x>y,请交换x,y),k=2表示修改。

输出格式

对于每个查询指令输出一个整数表示答案。

每个答案占一行。

数据范围

N500000,M100000

输入样例:

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

输出样例:

2
-1






解题报告:
区间最大连续子段和,根据区间的可见性,咱们要在线段树的基础上增加lmax,rmax,分别是管理前缀最带子段和和后缀最大子段和,
然后再区间[l,r]这个区间的最大子段和就是左区间的最大子段和,右区间的最大子段和,以及左右区间结合在一起中间的最大子段和。

ac代码:
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 
  5 const int maxn=500001;
  6 ll maxx(ll a,ll b,ll c)
  7 
  8     return max(a,max(b,c));
  9 
 10 struct node
 11 
 12     int l,r;
 13     ll lmax,rmax,sum,dat;
 14     //lmax 区间最大前缀和
 15     //rmax 区间最大后缀和
 16     //dat 最大子段和 
 17     //sum  区间全加起来的值 
 18     int mid()
 19     
 20         return (l+r)>>1;
 21     
 22 tree[maxn<<2];
 23 
 24 void pushup(int rt)
 25 
 26     tree[rt].lmax=maxx(tree[rt<<1].sum,tree[rt<<1].sum+tree[rt<<1|1].lmax,tree[rt<<1].lmax);
 27     tree[rt].rmax=maxx(tree[rt<<1|1].sum,tree[rt<<1|1].sum+tree[rt<<1].rmax,tree[rt<<1|1].rmax);
 28     tree[rt].dat=maxx(tree[rt<<1].dat,tree[rt<<1|1].dat,tree[rt<<1].rmax+tree[rt<<1|1].lmax);
 29     tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
 30 
 31 
 32 void build(int l,int r,int rt)
 33 
 34     tree[rt].l=l;
 35     tree[rt].r=r;
 36     if(l==r)
 37     
 38         scanf("%lld",&tree[rt].dat);
 39         tree[rt].sum=tree[rt].lmax=tree[rt].rmax=tree[rt].dat;
 40         return;
 41     
 42     int m=tree[rt].mid();
 43     build(l,m,rt<<1);
 44     build(m+1,r,rt<<1|1);
 45     pushup(rt);
 46 
 47 void update(int rt,int x,int y)
 48 
 49     if(tree[rt].l==tree[rt].r)
 50     
 51         tree[rt].sum=tree[rt].lmax=tree[rt].rmax=tree[rt].dat=y;
 52         return;
 53     
 54     int m=tree[rt].mid();
 55     if(x<=m)
 56         update(rt<<1,x,y);
 57     else
 58         update(rt<<1|1,x,y);
 59     pushup(rt);
 60 
 61 
 62 node query(int rt,int l,int r)
 63 
 64     if(tree[rt].l==l&&tree[rt].r==r)
 65     
 66         return tree[rt];
 67     
 68     int m=tree[rt].mid();
 69     if(m>=r)
 70     
 71         return query(rt<<1,l,r);
 72     
 73     else if(m<l)
 74     
 75         return query(rt<<1|1,l,r);
 76     
 77     else
 78     
 79         node ls=query(rt<<1,l,m);
 80         node rs=query(rt<<1|1,m+1,r);
 81         node ans;
 82         ans.dat=maxx(ls.dat,rs.dat,ls.rmax+rs.lmax);
 83         ans.lmax=maxx(ls.sum,ls.lmax,ls.sum+rs.lmax);
 84         ans.rmax=maxx(rs.sum,rs.rmax,rs.sum+ls.rmax);
 85         ans.sum=ls.sum+rs.sum;
 86         return ans;
 87     
 88 
 89 int main()
 90 
 91     int n,m;
 92     cin>>n>>m;
 93     build(1,n,1);
 94     int i,j,t;
 95     for(i=0;i<m;i++)
 96     
 97         scanf("%d",&j);
 98         if(j==1)
 99         
100             int a,b;
101             scanf("%d%d",&a,&b);
102             if(a>b)
103                 swap(a,b);
104             node ans=query(1,a,b);
105             printf("%d\\n",ans.dat);
106         
107         else
108         
109             int x,y;
110             scanf("%d%d",&x,&y);
111             update(1,x,y);
112         
113     
114 
115 
116 /*
117 5 3
118 1 2 -3 4 5
119 1 2 3
120 2 2 -1
121 1 3 2
122 */

 




以上是关于你能回答这些问题吗 (线段树)的主要内容,如果未能解决你的问题,请参考以下文章

线段树你能回答这问题吗?

线段树入门+例题

ACM入门之线段树习题

codevs 1080 线段树练习

线段树练习 codevs 1080

线段树练习 1,2