title link:Sicily 1136
Problem Solving Ideas:
The maximum number of sub-arrays within a range is required, and access may be frequent and time complexity needs to reach O (n*logn), so it is natural to think of the line segment tree . We can use the line segment tree to save the maximum sub-array of the interval, but think about it again is not right, if the access to the interval across the two cells how to break, so, this is not just a simple interval of continuous and the problem, but also a little bit of skill.
How do you get the maximum subarray, remember that the introduction to the algorithm introduces a method of using divide and conquer method to find the maximal sub-array (the largest sub-array of divide-and-conquer method)?
Let's say we ask for the maximum sub-array of the interval [low, high], and the various information about [low, mid] and [Mid+1, High] (mid is the midpoint of the interval, the various information here is not determined), how do we get the largest subarray? Then there is the formula:
Root->max_sum=max (Root->l->max_sum, Root->r->max_sum, Root->l->lmax+root->r->rmax)
The Lmax here represents the maximum continuity of the right boundary of the interval, and the Rmax is the largest continuous with the left boundary, and because the topic ultimately needs to find the interval, the boundaries of each seed array need to be recorded, the following is the definition of the segment tree structure:
struct node{int left,right,sum; //interval left and right boundary, interval and long long Lmax,rmax; //contains the maximum contiguous and of the right and left boundaries. int l_index,r_index; //lmax left boundary, Rmax right boundary long long max_sum; //maximum continuous and int left_bound,right_bound; //the largest continuous and left and right boundary node *l,*r; Node (int l,int R): Left (L), right (R), L (null ), R (null ) {}};
Then Lmax and Rmax also have the formula:
Root->lmax=max (Root->r->lmax, Root->l->lmax+root->r->sum)
Root->rmax=max (Root->l->rmax, Root->r->rmax+root->l->sum)
Finally there is a detail, the answer of the interval [I, J] I, J is the smallest, there is no big problem!
AC Code:
#include <bits/stdc++.h>usingnamespace Std;intn,a[100005];structnode{int left,right,sum; Long Long Lmax,rmax; int l_index,r_index; Long Long max_sum; int left_bound,right_bound; Node *l,*r; Node (int l,int R): Left (L), right (R), L (NULL), R (NULL){}};voidPUSH_UP (node* root) {root->sum=root->l->sum+root->r->sum; root->lmax=root->r->lmax,root->l_index=root->r->l_index; From mid to leftif(Root->l->lmax+root->r->sum >= Root->lmax) {root->lmax=root->l->lmax+root->r->sum; root->l_index=root->l->l_index; } root->rmax=root->l->rmax,root->r_index=root->l->r_index; From mid to rightif(Root->r->rmax+root->l->sum > Root->rmax) {root->rmax=root->r->rmax+root->l->sum; root->r_index=root->r->r_index; } root->max_sum=root->l->max_sum; Max Sum root->left_bound=root->l->left_bound; root->right_bound=root->l->right_bound;if(Root->l->lmax+root->r->rmax > Root->max_sum) {root->max_sum=root->l->lmax+root->r->rmax; root->left_bound=root->l->l_index; root->right_bound=root->r->r_index; }if(Root->r->max_sum > Root->max_sum) {root->max_sum=root->r->max_sum; root->left_bound=root->r->left_bound; root->right_bound=root->r->right_bound; }}voidCreate (node* root) {int l=root->left,r=root->right;if(L<r) {int mid= (L+R) >>1; Root->l=new node (l,mid); Root->r=new Node (mid+1, R); Create (ROOT->L); Create (ROOT->R); Push_up (root); }Else{root->sum=a[l]; root->lmax=root->rmax=root->sum; Root->left_bound=root->right_bound= root->l_index=root->r_index=l; root->max_sum=root->sum; }}nodeQuery (node* root,int l,int R) {if(root->left==l&&root->right==r) return *root; int mid= (root->left + root->right)/2;if(mid>=r) return query (ROOT->L,L,R);Else if(L>MID) return query (ROOT->R,L,R);Else{node Ans_l=query (root->l,l,mid), Ans_r=query (root->r,mid+1, R); Node ans (l,r); Ans.sum=ans_l.sum+ans_r.sum; Ans.lmax=ans_r.lmax,ans.l_index=ans_r.l_index; From mid to leftif(Ans_l.lmax+ans_r.sum >= Ans.lmax) Ans.lmax=ans_l.lmax+ans_r.sum,ans.l_index=ans_l.l_index; Ans.rmax=ans_l.rmax,ans.r_index=ans_l.r_index; From mid to rightif(Ans_r.rmax+ans_l.sum > Ans.rmax) ans.rmax=ans_r.rmax+ans_l.sum,ans.r_index=ans_r.r_index; Ans.max_sum=ans_l.max_sum,//max sum Ans.left_bound=ans_l.left_bound, a Ns.right_bound=ans_l.right_bound;if(Ans_l.lmax+ans_r.rmax > Ans.max_sum) {Ans.max_sum=ans_l.lmax+ans_r.rmax; Ans.left_bound=ans_l.l_index,ans.right_bound=ans_r.r_index; }if(Ans_r.max_sum > Ans.max_sum) ans.max_sum=ans_r.max_sum, Ans.left_bound=ans_r.left_bound, Ans.right_bound=ans_r.right_bound; return ans; } }voidPrint (node* root)//test with {printf ("l:%d r:%d sum:%d\n", root->left,root->right,root->sum); printf"mid_to_left:%d:%d\n", Root->l_index,root->lmax); printf"mid_to_right:%d:%d\n", Root->r_index,root->rmax); printf"max:l:%d r:%d sum:%d\n\n", root->left_bound,root->right_bound,root->max_sum);if(root->l) print (root->l);if(root->r) print (root->r);}intMain () {int n,m; scanf"%d%d", &n,&m); for (int i=1; i<=n;i++) scanf ("%d", &a[i]); node* root=new Node (1, n); Create (root);//print (root); int x, y; while (m--){scanf ("%d%d", &x,&y); Node Tmp=query (root,x,y); printf"%d%d%lld\n", tmp.left_bound,tmp.right_bound,tmp.max_sum); } return0;}
Summary:
1, Segment tree is really a good thing, with the interval-related queries, consider it more;
2, the method of splitting and administering the maximum subarray is also very important;
3, pay attention to details, do not hand cheap!!!
Sicily 1136 (segment tree + maximum sub-array)