Thursday, August 1, 2013

SPOJ-2916::Can you answer these queries V

http://www.spoj.com/problems/GSS5/

Typical problem statement can be seen as below.

Problem: Given a array of numbers a[1...n] , and a Query(x1,y1,x2,y2).
Query(x1,y1,x2,y2) = Max { A[i]+A[i+1]+...+A[j] ; x1 <= i <= y1 , x2 j <= y2 and x1 <= x2 , y1 <= y2 }.

Lets analyze this query...
Wait a minute...!!
    Have you read my post on GSS1 problem ??
    Have you ever Solved GSS1 problem ??
If your answer is NO, then I suggest you to do that problem first.
http://code.karumanchi.me/2013/07/spoj-1043can-you-answer-these-queries-i.html


Here two cases araises based on {x1 <= i <= y1 , x2 j <= y2 and x1 <= x2 , y1 <= y2 }.
 Case-1: (x1,y1) and (x2,y2) doesn't overlap.
 Case-2: (x1,y1) and (x2,y2) overlaps.

Case-1::No Overlapping
 result would be (x1,y1).bestRightSum + (y1+1,x2-1).Sum +(x2,y2).bestLeftSum;

Case-2::No Overlapping
 result would be max of
   {
   (x1,x2-1).bestRightSum  + (x2,y2).bestLeftSum,
   (x1,y1).bestRightSum  + (y1+1,y2).bestLeftSum,
   (x2,y1).bestSum
   }



Implementation of the Same - Solution
// =====================================================================================
//       Filename:  GSS5.cpp
//    Description:
//         Author:  BrOkEN@!
// =====================================================================================
#include<cassert>
#include<cctype>
#include<climits>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<bitset>
#include<deque>
#include<list>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<vector>
#include<fstream>
#include<iostream>
#include<sstream>
#include<streambuf>
#include<algorithm>
#include<iterator>
#include<new>
#include<string>
#include<utility>

template< class T >
inline T maxOfThree(T a, T b, T c){
    return max(max(a,b),c);
}

#define FOR(i,a,b) for(typeof((a)) i = (a); i <= (b) ; ++i )
#define REV_FOR(i,b,a) for(typeof((b)) i = (b); i >= (a) ; --i )
#define FOREACH(it,x) for(typeof((x).begin()) it=((x).begin()); it != ((x).end()); ++it)
#define REV_FOREACH(it,x) for(typeof((x).rbegin()) it=((x).rbegin()); it != ((x).rend()); ++it)


using namespace std;

typedef pair<int,int> PI;
typedef vector<PI> VI;

typedef struct node{
    int bestLeftSum,bestRightSum,Sum,bestSum;
   
    node merge(node& l,node& r){
        bestLeftSum = max(l.bestLeftSum,l.Sum+r.bestLeftSum);
        bestRightSum = max(l.bestRightSum+r.Sum,r.bestRightSum);
        Sum = l.Sum + r.Sum;
        bestSum = maxOfThree(l.bestSum,r.bestSum,l.bestRightSum+r.bestLeftSum);
    }
   
    node setNode(int val){
        bestLeftSum = bestRightSum = Sum = bestSum = val;
    }
       
} node;


const int MAX = 1<<14;

node T[MAX<<1];
int A[MAX];

void init(int Node,int i,int j){
    if(i==j){
        T[Node].setNode(A[i]);
        return;
    }else{
        int m = (i+j)/2;
        init(2*Node,i,m);
        init(2*Node+1,m+1,j);
        T[Node].merge(T[2*Node],T[2*Node+1]);
    }
}

node range_query(int Node,int i,int j,int L,int R){
    if(L > R) return T[0];
    if(i==L && R==j){
        return T[Node];
    }else{
        int m = (i+j)/2;
        if(R<=m){
            return range_query(2*Node,i,m,L,R);
        }else if(L>m){
            return range_query(2*Node+1,m+1,j,L,R);
        }else{
            node resultNode,left,right;
            left = range_query(2*Node,i,m,L,m);
            right = range_query(2*Node+1,m+1,j,m+1,R);
            resultNode.merge(left,right);
            return resultNode;
        }
    }
}

int query(int N,int x1,int y1,int x2,int y2){
    int result =0;
    if(y1<x2){
        result += range_query(1,0,N-1,x1,y1).bestRightSum;
        result += range_query(1,0,N-1,y1+1,x2-1).Sum;
        result += range_query(1,0,N-1,x2,y2).bestLeftSum;
    }else{
        result += maxOfThree(
                    range_query(1,0,N-1,x1,x2-1).bestRightSum  + range_query(1,0,N-1,x2,y2).bestLeftSum,
                    range_query(1,0,N-1,x1,y1).bestRightSum  + range_query(1,0,N-1,y1+1,y2).bestLeftSum,
                    range_query(1,0,N-1,x2,y1).bestSum
                    );
           
    }
    return result;
}

int main(){
    int T=0;
    scanf("%d",&T);

    int N=0,Q=0,x1=0,y1=0,x2=0,y2=0;
    FOR(t,1,T){
        scanf("%d",&N);
        FOR(i,0,N-1){scanf("%d",&A[i]);}
        init(1,0,N-1);
        scanf("%d",&Q);
        FOR(q,1,Q){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            --x1;--y1;--x2;--y2;
            printf("%d\n",query(N,x1,y1,x2,y2));
        }
    }

    return 0;
}

12 comments:

  1. in case of overlapping intervals (x1,y1,)and (x2,y2) , what's the difference between (x1,x2-1).bestRightSum + (x2,y2).bestLeftSum and (x1,x2).bestRightSum + (x2+1,y2).bestLeftSum (<--This cost me 2 Wrong Answer)

    ReplyDelete
  2. Hey nice doubt.
    Lets consider your statement. i.e. (x1,x2).bestRightSum + (x2+1,y2).bestLeftSum

    (x1,x2).bestRightSum will be equal to max( (x1,x2-1).bestRightSum+x2 , x2 ).
    So If you have a case where max will return only x2. Your logic will fail and (x1,x2-1).bestRightSum is not considered at all.

    Coming to the logic, if the resulting range is [i,j].
    as per the first sub-case in Overlapping intervals, 'i' will be in [x1,x2) and 'j' will be in [x2,y2].

    'i' will be in [x1,x2) and 'j' will be in [x2,y2] ==> 'i' will be in [x1,x2-1] and 'j' will be in [x2,y2]
    Hope this will clear your doubt. :)

    ReplyDelete
    Replies
    1. I'm sorry but can you explain why our logic fails if x2 is returned? If we are concerned with the greatest bestRightSum in
      (x1,x2), and x2 happens to be that value, then shouldn't x2 be returned?

      Delete
    2. If we are concerned with bestRightSum in (x1,x2) and if x2 is returned...then as per your statement
      "(x1,x2).bestRightSum + (x2+1,y2).bestLeftSum == x2 + (x2+1,y2).bestLeftSum"
      so "x2 + (x2+1,y2).bestLeftSum" == "(x2,y2).bestLeftSum".
      But you never considered (x1,x2-1).bestRightSum which could contribute to the whole range.
      refer to my earlier comment.

      Delete
  3. hey in the overlapping case why can't we choose (x1,x2-1).bestrightsum+(x2,y1).sum+(y1+1,y2).bestleftsum or (x1,x2).bestrightsum+(x2+1,y1-1).sum+(y1,y2).bestleftsum ?

    ReplyDelete
  4. Hi Ankit,

    Lets consider below cases.

    Case-1 : (x1,x2-1).bestrightsum+(x2,y1).sum+(y1+1,y2).bestleftsum - as you mentioned.
    in this case, it's not always true that (x2,y1).sum will contribute towards the best maximum sum in the range(x2,y2).
    So there might be case like, where
    (x2,y1).sum < (x2,NUM).sum and NUM<y1 ; provided (NUM,y1) containing negative values.

    Case-2: (x1,x2).bestrightsum+(x2+1,y1-1).sum+(y1,y2).bestleftsum
    Refer to my previous comment for considering (x1,x2).bestrightsum. Case-1 explanation is also applicable here.
    (x2+1,y1-1).sum contribution towards the the best sum is not consistent always.

    ReplyDelete
  5. Yes i got it. Thanks :)

    ReplyDelete
  6. Thanks for the helpful post! If x2 is returned thats means (x1,x2-1).bestRightSum is negative isn't it? Then why should we still take it into account?

    ReplyDelete
    Replies
    1. Hi Minh, please refer to my comment @January 28, 2015 at 11:26 PM

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. In case of no overlapping why you are adding (y1+1,x2-1).Sum this as it does not lie in the interval

    ReplyDelete
    Replies
    1. In case of no overlap, Query should return Sum of elements from X1 to Y2.
      [X1,Y2] = [X1,Y1] + (Y1,X2) + [X2,Y2] and (Y1,X2) is an interval which is nothing but [Y1+1, X2-1].
      So [X1,Y2] = [X1,Y1] + [Y1+1, X2-1] + [X2,Y2]

      Delete