UVa Ray, Pass me the dishes! (线段树)

来源:互联网 发布:c语言水仙花数程序 编辑:程序博客网 时间:2024/05/16 01:58

白书上的线段树例题。

题意 : 给你一个数组,然后有m次询问,每次询问一个区间,返回在这个区间里面最大的连续和的起始和结束位置、

思路 :每个节点记录前缀max_pre和和后缀和max_suf来维护它的最大连续和max_sub。(其实思路白书上讲了,就是代码实现而已)需要注意的是这道题目的max_pre,max_suf,max_sub都是需要用long long 来保存的。


#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef long long lld;const int MAXN = 500005;const int INF = 100000007;struct MAX{lld Max;int l,r;};struct node{MAX sub, pre, suf;lld sum;}ans[MAXN<<2];int n,m;void init(node &a,int v){MAX  e;e.Max = v;e.l = -INF; e.r = INF;a.pre = a.sub = a.suf = e;a.sum = v;}void push_up(node &mid,node &ll,node &rr){mid.sum = ll.sum + rr.sum;if (ll.pre.Max >= rr.pre.Max + ll.sum){mid.pre = ll.pre;}else{mid.pre.Max = rr.pre.Max + ll.sum;mid.pre.l = ll.pre.l;mid.pre.r = rr.pre.r;}if (rr.suf.Max > rr.sum + ll.suf.Max){mid.suf = rr.suf;}else{mid.suf.Max = rr.sum + ll.suf.Max;mid.suf.l = ll.suf.l;mid.suf.r = rr.suf.r;}lld temp = ll.suf.Max + rr.pre.Max;lld t1 = ll.sub.Max, t2 = rr.sub.Max;if (t1 >= temp && t1 >= t2){mid.sub = ll.sub;}else if (temp >= t1 && temp >= t2){mid.sub.Max = temp;mid.sub.l = ll.suf.l;mid.sub.r = rr.pre.r;}else{mid.sub = rr.sub;}}void update(int rt,int L,int R,int p,int v){if (L == R){ans[rt].sub.Max = ans[rt].pre.Max = ans[rt].suf.Max = v;ans[rt].sum = v;ans[rt].sub.l = ans[rt].sub.r = p;ans[rt].pre.l = ans[rt].pre.r = p;ans[rt].suf.l = ans[rt].suf.r = p;}else{int M = (L + R) >> 1;if (p <= M)update(rt<<1,L,M,p,v);else update(rt<<1|1,M+1,R,p,v);if (ans[rt<<1].sum != -INF){if (ans[rt<<1|1].sum != -INF)push_up(ans[rt],ans[rt<<1],ans[rt<<1|1]);else ans[rt] = ans[rt<<1];}else ans[rt] = ans[rt<<1|1];}}node query(int rt,int L,int R,int l,int r){int M = (L + R) >> 1;node tl,tr,res;init(tl,-INF); init(tr,-INF);if (L >= l && R <= r)return ans[rt];if (M >= l){tl = query(rt<<1,L,M,l,r);}if (r > M){tr = query(rt<<1|1,M+1,R,l,r);}if (tl.sum != -INF){if (tr.sum != -INF){push_up(res,tl,tr);return res;}else return tl;}else return tr;}int main(){int cas = 1 , i;while (scanf("%d%d",&n,&m) == 2){for (i = 1;i <= 4*n;i++)init(ans[i],-INF);for (i = 1;i <= n;i++){int a;scanf("%d",&a);update(1,1,n,i,a);}printf("Case %d:\n",cas++);while (m--){int ql,qr;scanf("%d%d",&ql,&qr);node  res = query(1,1,n,ql,qr);printf("%d %d\n",res.sub.l,res.sub.r);}}return 0;}


原创粉丝点击