Here you will find solutions of many problems on spoj. If you want solution of some problem which is not listed in blog or have doubt regarding any spoj problem (which i have solved) or any programming concept (data structure) you can mail me @ raj.nishant360@gmail.com

And my humble request to you all that don't copy the code only try to understand the logic and algorithm behind the code. I have started this because if you tried as hard as you can and still can't find any solution to the problem then you can refer to this.
You can read my answer how to start competitive programming CLICK HERE
Showing posts with label Segment Tree. Show all posts
Showing posts with label Segment Tree. Show all posts

Sunday, October 18, 2015

PATULJCI-Snow White and the N dwarfs

Snow White and the N dwarfs

Given below code is for patuljci spoj or snow white and the N dwarfs spoj .

Hint:- source( http://hsin.hr/ )

For now, forget about the problem we are solving.

Suppose we had a sequence of integers and an algorithm like this:

while there are different numbers in the sequence
    select any two different numbers from the sequence
        and erase them

For example if the sequence were:
1 2 3 1 2 3 2 3
the algorithm could have done this:
1 2 3 1 2 3 2 3 --> 3 1 2 3 2 3 -> 1 3 2 3 -> 3 3
Note that we could also end up with other sequences if we selected pairs in a different way.

Let candidate be the number that is left in a sequence (3 in the example above).
Let count be the number of numbers left in a sequence (2 in the example above).

The cool thing about the algorithm is that if there is a number that appears more than N/2 times in the sequence it must end up as a candidate no matter the way we select pairs. Intuitively, we don't have enough other numbers to kill all of the candidate numbers. So we can choose our own way to select pairs. Let's do it recursively like this.

1) Split the sequence S in two halves L and R.
2) Run the recursive algorithm on sequence L to get L.candidate and L.count
3) Run the recursive algorithm on sequence R to get R.candidate and R.count
4) Kill the remaining pairs among L.count + R.count numbers that are left.
The step #4 can be done very efficiently like this:

if L.candidate == R.candidate
    S.candidate = L.candidate
    S.count = L.count + R.count
else
    if L.count > R.count
        S.candidate = L.candidate
        S.count = L.count - R.count
    else
        S.candidate = R.candidate
        S.count = R.count - L.count
    end
end

So, we can use this idea to build the interval tree, every node containing info (candidate and count) about the sub-sequence it represents. We can also query the interval tree to get candidate number for any interval [A, B]. Then we can use binary search to count the number of appearances of the candidate number in the interval and determine if the picture is pretty or not.




/*
===================================================
Name :- Nishant Raj
Email :- raj.nishant360@gmail.com
College :- Indian School of Mines
Branch :- Computer Science and Engineering
Time :- 18 October 2015 (Sunday) 17:10
===================================================*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair < int , int >
#define pb push_back
#define mp make_pair
#define mod 1000000009
template<class T>
class segmentTree{
public:
    segmentTree(){
        height = 1;
        left_most = 1<<height;
        right_most = (left_most<<1) - 1; 
        tree = new T[right_most];
    }
    segmentTree(int s){ 
        size=s;
        height = ceil(log2(s));
        left_most = 1<<height;
        right_most = (left_most<<1) - 1;
        tree = new T[right_most+9];
    }
    void init(T * arr){
        build(arr);
    }
    void Update(int pos , T val){
        point_update(1 , left_most , right_most , left_most+pos , val);
    }
    void Update(int l , int r , T val){
        range_update(1 , left_most , right_most , left_most+l , left_most+r , val);
    }
    T Query(int pos){
        return point_query(1 , left_most , right_most , left_most+pos);
    }
    T Query(int l ,int r){
        return range_query(1 , left_most , right_most , left_most+l , left_most+r);
    }
private:
    T *tree;
    int size , left_most , right_most , height;
    void build(T * arr){
        for(int i = 0 ; i < size ; i++)
            tree[left_most+i] = arr[i];
        initalize(1 , left_most , right_most); 
    }
    void initalize(int root , int left_most , int right_most){
        if(left_most == right_most) return;
        int mid = (left_most + right_most)>>1 , l_child = (root<<1)  , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        initalize(l_child , left_most , mid);
        initalize(r_child , mid+1 , right_most);
        tree[root].merge(tree[l_child] , tree[r_child]);
    }
    void point_update(int root , int left_most , int right_most , int pos , T val){
        if(left_most == right_most && root == pos) { tree[root].update(val); return ;}
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        if(pos <= mid) point_update(l_child , left_most , mid , pos , val);
        else point_update(r_child , mid+1 , right_most , pos , val);
        tree[root].merge(tree[l_child] , tree[r_child]);
    }
    void range_update(int root , int left_most , int right_most , int l , int r , T val){
        if(l <= left_most && r >= right_most){ tree[root].update(val);return;}
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        if(l <= mid) range_update(l_child , left_most , mid, l , r , val);
        if(r > mid) range_update(r_child , mid+1 , right_most , l , r , val);
        tree[root].merge(tree[l_child] , tree[r_child]);
    }
    T range_query(int root , int left_most ,int right_most ,int l , int r){
        if( l <= left_most && r >= right_most )
            return tree[root];
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        T l_node  , r_node , temp;
        if(l <= mid) l_node = range_query(l_child , left_most , mid , l , r );
        if(r > mid) r_node = range_query(r_child , mid+1 , right_most , l , r );
        tree[root].merge(tree[l_child] , tree[r_child]);
        temp.merge(l_node , r_node);
        return temp;
    }
    T point_query(int root , int left_most , int right_most , int pos){
        if(left_most == right_most && root == pos) return tree[root];
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        T temp;
        tree[root].split(tree[l_child] , tree[r_child]);
        if(pos <= mid) temp = point_query(l_child , left_most , mid , pos);
        else temp = point_query(r_child , mid+1 , right_most , pos);
        tree[root].merge(tree[l_child] , tree[r_child]);
        return temp;
    }
};
class node{
public:
    int count , number;
    void merge(node &l , node &r){
        if(l.number == r.number){
            count = l.count + r.count;
            number = l.number;
        } else {
            if( l.count > r.count ){
                count = l.count - r.count;
                number = l.number;
            } else{
                count = r.count - l.count;
                number = r.number;
            }
        }
    }
    void split(node &a , node &b){
    }
    void update(node &a){
    }
    node(){
        count = 0  , number = 0;
    }
    node(int num){
        count = 1;
        number = num;
    }
};
node arr[300009];
vector<int> Index[100009];
int main(){
    int n , c;
    scanf("%d%d",&n , &c);
    int temp;
    for(int i = 0; i < n ; i++){
        scanf("%d",&temp);
        Index[temp].pb(i);
        arr[i] = node(temp);
    }
    segmentTree<node> s(n);
    s.init(arr);
    int q , l , r;
    scanf("%d",&q);
    while(q--){
        scanf("%d%d",&l,&r);
        l-- , r--;
        int num = s.Query(l , r).number;
        int count = upper_bound(Index[num].begin() , Index[num].end() , r) - lower_bound(Index[num].begin() , Index[num].end() , l);
        int req = r - l +1;
        if(count*2 > req){
            printf("yes %d\n", num);
        } else
            printf("no\n");
    }
    return 0;
} 

Friday, October 16, 2015

SEGSQRSS-Sum of Squares with Segment Tree

Sum of Squares with Segment Tree

Given below c++ code is for segsqrss spoj or sum of squares with segment tree spoj.

Main logic of code is within Merge and Split function in class 'node'




/*
===================================================
Name :- Nishant Raj
Email :- raj.nishant360@gmail.com
College :- Indian School of Mines
Branch :- Computer Science and Engineering
Time :- 16 October 2015 (Friday) 02:09
===================================================*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define pii pair < int , int >
#define pb push_back
#define mp make_pair
#define mod 1000000009
template<class T>
class segmentTree{
public:
    segmentTree(){
        height = 1;
        left_most = 1<<height;
        right_most = (left_most<<1) - 1; 
        tree = new T[right_most];
    }
    segmentTree(int s){ 
        size=s;
        height = ceil(log2(s));
        left_most = 1<<height;
        right_most = (left_most<<1) - 1;
        tree = new T[right_most+9];
    }
    void init(T * arr){
        build(arr);
    }
    void fill_ans(){
        initalize(1,left_most,right_most);
        for(int i = left_most ;i< left_most+size ; i++){
            for(int j=1;j<=26;j++)
                if(tree[i].arr[j]){
                    cout<<char(j+96);
                    break;
                }
        }
    }
    void Update(int pos , T val){
        point_update(1 , left_most , right_most , left_most+pos , val);
    }
    void Update(int l , int r , T val){
        range_update(1 , left_most , right_most , left_most+l , left_most+r , val);
    }
    T Query(int pos){
        return point_query(1 , left_most , right_most , left_most+pos);
    }
    T Query(int l ,int r){
        return range_query(1 , left_most , right_most , left_most+l , left_most+r);
    }
private:
    T *tree;
    int size , left_most , right_most , height;
    void build(T * arr){
        for(int i = 0 ; i < size ; i++)
            tree[left_most+i] = arr[i];
        initalize(1 , left_most , right_most); 
    }
    void initalize(int root , int left_most , int right_most){
        if(left_most == right_most) return;
        int mid = (left_most + right_most)>>1 , l_child = (root<<1)  , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        initalize(l_child , left_most , mid);
        initalize(r_child , mid+1 , right_most);
        tree[root].merge(tree[l_child] , tree[r_child]);
    }
    void point_update(int root , int left_most , int right_most , int pos , T val){
        if(left_most == right_most && root == pos) { tree[root].update(val); return ;}
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        if(pos <= mid) point_update(l_child , left_most , mid , pos , val);
        else point_update(r_child , mid+1 , right_most , pos , val);
        tree[root].merge(tree[l_child] , tree[r_child]);
    }
    void range_update(int root , int left_most , int right_most , int l , int r , T val){
        if(l <= left_most && r >= right_most){ tree[root].update(val);return;}
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        if(l <= mid) range_update(l_child , left_most , mid, l , r , val);
        if(r > mid) range_update(r_child , mid+1 , right_most , l , r , val);
        tree[root].merge(tree[l_child] , tree[r_child]);
    }
    T range_query(int root , int left_most ,int right_most ,int l , int r){
        if( l <= left_most && r >= right_most )
            return tree[root];
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        tree[root].split(tree[l_child] , tree[r_child]);
        T l_node  , r_node , temp;
        if(l <= mid) l_node = range_query(l_child , left_most , mid , l , r );
        if(r > mid) r_node = range_query(r_child , mid+1 , right_most , l , r );
        tree[root].merge(tree[l_child] , tree[r_child]);
        temp.merge(l_node , r_node);
        return temp;
    }
    T point_query(int root , int left_most , int right_most , int pos){
        if(left_most == right_most && root == pos) return tree[root];
        int mid = (left_most + right_most)>>1 , l_child = root<<1 , r_child = (root<<1)+1;
        T temp;
        tree[root].split(tree[l_child] , tree[r_child]);
        if(pos <= mid) temp = point_query(l_child , left_most , mid , pos);
        else temp = point_query(r_child , mid+1 , right_most , pos);
        tree[root].merge(tree[l_child] , tree[r_child]);
        return temp;
    }
};
class node{
public:
    ll sum , sq_sum , lazy1 , lazy2;
    int child_count;
    void merge(node &a , node &b){
        sum = a.sum + b.sum;
        sq_sum = a.sq_sum + b.sq_sum;
        child_count = a.child_count + b.child_count;
        lazy1 = lazy2 = 0;
    }
    void split(node &a , node &b){
        if(lazy1){
            a.sq_sum += lazy1 * lazy1 * (ll)a.child_count + 2LL * lazy1 * a.sum;
            b.sq_sum += lazy1 * lazy1 * (ll)b.child_count + 2LL * lazy1 * b.sum;
            a.sum += lazy1 * a.child_count;
            b.sum += lazy1 * b.child_count;
            a.lazy1 += lazy1;
            b.lazy1 += lazy1;
            lazy1 = 0;
        }
        if(lazy2){
            a.sq_sum = a.child_count * lazy2 * lazy2;
            a.sum = a.child_count * lazy2;
            a.lazy2 += lazy2;
            b.sq_sum = b.child_count * lazy2 * lazy2;
            b.sum = b.child_count * lazy2;
            b.lazy2 += lazy2;
        }
    }
    void update(node &a){
        if(a.lazy1){
            sq_sum = sq_sum + a.lazy1 * a.lazy1 * child_count + 2LL * a.lazy1 * sum;
            sum += a.lazy1 * child_count;
            lazy1 += a.lazy1;
        }
        if(a.lazy2){
            sq_sum = child_count * a.lazy2 * a.lazy2;
            sum = child_count * a.lazy2;
            lazy2 += a.lazy2;
        }
    }
    node(){
        sum = sq_sum = lazy1 = lazy2 = 0;
        child_count = 0;
    }
    node(ll a , ll l1 , ll l2){ 
        sum = a;
        sq_sum = a*a;
        child_count = 1;
        lazy1 = l1;
        lazy2 = l2;
    }
};
node arr[100009];
int main(){
    int t;
    scanf("%d",&t);
    for(int test = 1 ; test <= t ; test++){
        int n , temp ,q;
        scanf("%d%d",&n,&q);
        segmentTree<node> s(n);

        for(int i =0;i<n;i++){
            scanf("%d",&temp);
            arr[i]=node(temp , 0 , 0);
        }
        s.init(arr);
        printf("Case %d:\n",test);
        while(q--){
            int l,r,k,val;
            scanf("%d%d%d",&k,&l,&r);
            l-- , r--;
            if(k == 2){
                printf("%lld\n",s.Query(l,r).sq_sum);
            }
            else if(k==1){
                scanf("%d",&val);
                s.Update(l , r , node(0 , val , 0));
            } else{
                scanf("%d",&val);
                s.Update(l , r , node(0 , 0 , val));
            }
        }
    }
    return 0;
}

Saturday, February 28, 2015

ORDERSET-Order statistic set

Order statistic set

Given below code is for ORDERSET spoj or Order statistics set spoj.

Explanation :- Here I have used Policy Based Data Structure of C++ ,  You can read about this Design , Using & Testing. And it support all basic STL functions and some extra of it owns.
Time :- 0.65 sec



#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<
int ,
null_type,
less<int>,
rb_tree_tag,
tree_order_statistics_node_update>pbd_set;
int main(){
    pbd_set s;
    int t;
    scanf("%d ",&t);
    while(t--){
        char typ;
        int n;
        scanf(" %c%d",&typ , &n);
        if(typ == 'I')
            s.insert(n);
        else if (typ == 'D')
            s.erase(n);
        else if (typ == 'K'){
            int ans;
            n--;
            if(s.find_by_order(n) != s.end()){
                ans = *s.find_by_order(n);
                printf("%d\n",ans);
            }
            else 
                printf("invalid\n");
        }
        else{
            int ans = s.order_of_key(n);
            printf("%d\n",ans);
        }
    }
    return 0;
}



My solution for ORDERSET spoj or Order statistic set spoj problem using BIT(Binary Index Tree)
Time:- 0.46 sec


#include <bits/stdc++.h>
using namespace std;
#define MAX 200005
#define pb push_back
int tree[200009], hash[200009], save[200009];
void update(int pos , int data){
    while(pos <= MAX){
        tree[pos]+= data;
        pos += (pos & (-pos));
    }
}
int read(int pos){
    int ans = 0;
    while(pos){
        ans += tree[pos];
        pos -= (pos & -pos);
    }
    return ans;
}
struct data{
    int pos , data , hash;
    char type;
};
data d[200009], query[200009];
bool cmp(const data &a , const data &b){
    return a.data == b.data ? a.pos < b.pos : a.data < b.data;
}
int b_search(int k){

    int low = 0 , high = 200000 , mid;
    while(low < high){
        mid = (low + high)>>1;
        if(read(mid) >= k)
            high = mid;
        else
            low = mid+1;
    }
    return low;
}
int main(){
    int q ;
    scanf("%d",&q);
    for(int i = 0 ; i < q ; i++){
        scanf(" %c%d",&d[i].type , &d[i].data);
        d[i].pos = i+1;
    }

    sort(d , d + q , cmp);
    
    int cnt = 1 , prev = d[0].data;
    d[0].hash = cnt;
    save[cnt]= d[0].data;
    for(int i = 1 ; i < q ; i++)
    {
        if(prev != d[i].data){
            prev = d[i].data;
            cnt++;
            d[i].hash = cnt;
            save[cnt] = d[i].data;
        }
        else
            d[i].hash = cnt;
    }

    
    for(int i = 0 ; i < q ; i++){
        query[d[i].pos] = d[i];
    }

    cnt = 0;
    for(int i = 1 ; i <= q ; i++){
        if(query[i].type == 'I'){
            if(!hash[query[i].hash]){
                cnt++;
                hash[query[i].hash] = 1;
                update(query[i].hash , 1);
            }
        }
        else if(query[i].type == 'D'){

            if(hash[query[i].hash]){
                cnt--;
                hash[query[i].hash] = 0;
                update(query[i].hash , -1);
            }
        }

        else if(query[i].type == 'K'){
            if(query[i].data > cnt)
                printf("invalid\n");
            else
                printf("%d\n",save[b_search(query[i].data)]);
        }
        else
            printf("%d\n",read(query[i].hash - 1));
    }
    return 0;
}



My solution for ORDERSET spoj or Order statistic set spoj using Height Balanced Tree(AVL Tree ) I copied AVL tree code from geeks for geeks . For learning AVL tree you can refer to geeks for geeks :- http://www.geeksforgeeks.org/avl-tree-set-2-deletion/
Time :- 0.67 sec


#include <bits/stdc++.h>
using namespace std;
class node{
public:
 int val , height , sum ;
 node * left , *right;
    node(){
        val = height = sum = 0;
        left = right = NULL;    
    }
};
int get_sum(node *x){
    
    if(x == NULL)
        return 0;
    return x->sum;
}
node *get_new_node(int key){

    node *temp = new node();
    temp->val =  key;
 temp->left = NULL;
 temp->right = NULL;
 temp->height = 1;
 temp->sum = 1;
    return temp;
}

bool find(int key , node *root){
 
 if(root == NULL)
  return false;
 if(key < root->val)
  return find(key , root->left);
 else if(key > root->val)
  return find(key , root->right);
 else
  return true;
}

int get_height(node *x){
 
 if(x==NULL)
  return 0;
 return x->height;
}

int get_diff(node *x){

    if(x == NULL)
        return 0;
    return get_height(x->left) - get_height(x->right);
}
node *left_rotate(node *x){
 
 node *y  = x->right;
 node *y_left = y->left;

 y->left = x;
 x->right = y_left;

 x->height = max(get_height(x->left) , get_height(x->right)) + 1;
    x->sum = get_sum(x->left) + get_sum(x->right) + 1;
    y->height = max(get_height(y->left) , get_height(y->right)) + 1;
    y->sum = get_sum(y->left) + get_sum(y->right) + 1;
    return y;
}

node *right_rotate(node *x){

    node *y = x->left;
    node *y_right = y->right;

    y->right = x;
    x->left = y_right;
    
    x->height = max(get_height(x->left) , get_height(x->right)) + 1;
    x->sum = get_sum(x->left) + get_sum(x->right) + 1;
    y->height = max(get_height(y->left) , get_height(y->right)) + 1;
    y->sum = get_sum(y->left) + get_sum(y->right) + 1;
    return y;
}
node *insert(node *root , int key){

    if(root == NULL)
        return get_new_node(key);

    if(key < root->val)
        root->left = insert(root->left , key);

    else
        root->right = insert(root->right , key);

    root->height = max(get_height(root->left) , get_height(root->right)) + 1;
    root->sum = get_sum(root->left) + get_sum(root->right) + 1;
    int diff ;
    if(root == NULL)
        diff = 0;
    else
        diff = get_height(root->left) - get_height(root->right);

    if(diff > 1 && key < root->left->val)
        return right_rotate(root);
    if(diff < -1 && key > root->right->val)
        return left_rotate(root);
    if(diff > 1 && key > root->left->val){
        root->left = left_rotate(root->left);
        return right_rotate(root);
    }
    if(diff < -1 && key < root->right->val){
        root->right = right_rotate(root->right);
        return left_rotate(root);    
    }
    
    return root;
}
node *del(node * root , int key){

    if(root == NULL)
        return root;
    
    if(key < root->val)
        root->left = del(root->left , key);
    else if(key > root->val)
        root->right = del(root->right , key);

    else{
        
        if(root->left == NULL || root->right == NULL){
            
            node *temp = root->left ? root->left : root->right;
            if(temp == NULL){
                
                temp = root;
                root = NULL;
            }
            else
                *root = *temp;        
        }
        else{
            
            node *temp = root->right;
            while(temp->left != NULL)
                temp = temp->left;
            
            root->val = temp->val;

            root->right = del(root->right , temp->val);        
        }
    }
    
    if(root == NULL)
        return root;
    root->height = max(get_height(root->left) , get_height(root->right)) + 1;
    root->sum = get_sum(root->left) + get_sum(root->right) + 1;
    int diff = get_height(root->left) - get_height(root->right);
    
    if (diff > 1 && get_diff(root->left) >= 0)
        return right_rotate(root);
 
    if (diff > 1 && get_diff(root->left) < 0)
    {
        root->left =  left_rotate(root->left);
        return right_rotate(root);
    }
 
    if (diff < -1 && get_diff(root->right) <= 0)
        return left_rotate(root);
 
    if (diff < -1 && get_diff(root->right) > 0)
    {
        root->right = right_rotate(root->right);
        return left_rotate(root);
    }
    return root;
}
int get_by_order(node *root , int key){

    if(root == NULL)
        return 0;
    int left_size = get_sum(root->left);
    if(left_size == key)
        return root->val;
    if(key < left_size)
        return get_by_order(root->left , key);
    else
        return get_by_order(root->right , key - left_size - 1);
}
int order_of_key(node *root , int key){

    if(root == NULL)
        return 0;

    if(key < root->val)
        return order_of_key(root->left , key);
    else if(key == root->val){
        if(root->left != NULL)
            return get_sum(root->left) + 1;
        else 
            return 1;
    }
    else
    {
        if(root->left != NULL )
            return get_sum(root->left) + 1 + order_of_key(root->right , key);
        else
            return 1 + order_of_key(root->right , key);
    }
}

int main(){
    
    int q;
    scanf("%d",&q);
    node *root = NULL;
    while(q--){

        char c ;
        int value;
        scanf(" %c%d",&c , &value);
        if(c=='I'){

            if(!find(value , root)){
                root = insert(root , value) ;
            }
        }
        else if(c == 'D'){
            root = del(root , value ) ;
        }
        else if(c == 'C'){
            int ans = order_of_key(root , value);
            if(find(value , root))
                printf("%d\n",ans - 1);
            else
                printf("%d\n",ans);
        }
        else
        {
            value--;
            if(root == NULL)
                printf("invalid\n");
            else if( root->sum <= value)
                printf("invalid\n");
            else
                printf("%d\n",get_by_order(root , value));
        }
    }
    return 0;
}

Sunday, October 5, 2014

FREQUENT-Frequent values

Frequent values

Given below c++ code for frequent spoj or frequent values spoj .

This question is simple implementation of segment tree so if you don,t know segment tree first read it and then try it. you can read it from HERE

More easy question on segment tree


#include <bits/stdc++.h>
using namespace std;
struct node
{
  int res,pre,suf,pv,sv;
  void merge(node a,node b)
  {
    pre = a.pre;
    suf = b.suf;
    pv = a.pv;
    sv = b.sv;
    if(a.pv == b.pv )
      pre = a.pre + b.pre;
    if(a.sv == b.sv)
      suf = a.suf + b.suf;
    res = max(a.res,b.res);
    if(a.sv == b.pv)
      res = max(res , a.suf + b.pre);
  }
    node(){
      res = pre = suf = sv = pv = 0;
    }
    node(int val){
      res = pre = suf =1;
      sv = pv = val;
    }
}tree[500000];
void create(int pos)
{
  pos>>=1;
  while(pos){
    tree[pos].merge(tree[pos<<1],tree[(pos<<1)+1]);
    pos>>=1;
  }
}
node query(int root,int l_most,int r_most,int l,int r)
{
  if(l_most >= l && r_most <= r)
    return tree[root];
  int l_child = (root<<1) , r_child = l_child + 1,mid = (l_most + r_most )>>1;
  node left=node(),right = node();
  if(l<=mid)
    left = query(l_child,l_most,mid,l,r);
  if(r>mid)
    right = query(r_child,mid+1,r_most,l,r);;
  node temp = node();
  temp.merge(left,right);
  return temp;
}
int main()
{
  int n,q;
  while (1){
  scanf("%d",&n);
  if (n==0) break;
  scanf("%d",&q);
  int k = ceil(log(n)/log(2));
  int pos = (1<<k),temp;
  for(int i=0;i<n;i++){
    scanf("%d",&temp);
    tree[pos+i] = node(temp);
    create(pos+i);
  }
  for(int i=0;i<q;i++){
    int l,r;
    scanf("%d%d",&l,&r);
    printf("%d\n",query(1,1,pos,l,r).res);
  }}
  return 0;
}


Saturday, August 23, 2014

Segment tree GSS3 & GSS1

First of all read about segment tree and it basic functioning. You can read it from HERE .

Given below code is for GSS3 & GSS1 spoj .

Here i have implemented segment tree as given in above link.



//for GSS1 remove update part from main function

#include <bits/stdc++.h>
using namespace std;
#define INT -1000000
int k;
struct node
{
    int result,pre,suf,sum;
    void split(node &a , node &b){}
    void merge(node a , node b)
    {
        sum = a.sum + b.sum;
        pre = max(a.pre , (a.sum + b.pre));
        suf = max(b.suf , (b.sum + a.suf));
        result = max(a.suf + b.pre,max(a.result , b.result));
    }
    node()
    {
        result = pre = suf = sum = INT;
    }
    node(int temp)
    {
        result = pre = suf = sum = temp;
    }
}tree[131080];
void update(int pos)
{
    pos>>=1;
    while(pos!=0)
    {
        tree[pos].merge(tree[pos*2],tree[pos*2 + 1]);
        pos>>=1;
    }
}
node range_query(int root , int left_most , int right_most , int l ,int r)
{
    if( l <= left_most && r >= right_most )
        return tree[root];

    int l_child = (root<<1) , r_child = l_child + 1 , mid = (left_most + right_most )>>1 ;

    tree[root].split(tree[l_child],tree[r_child]);

    node l_node = node() , r_node = node();

    if(l <= mid)
        l_node = range_query(l_child , left_most , mid , l , r);
    if(r > mid)
        r_node = range_query(r_child , mid + 1 , right_most, l , r);

    tree[root].merge(tree[l_child] , tree[r_child]);

    node temp = node();
    temp.merge(l_node,r_node);

    return temp;
}
int main()
{
    int n,temp,l,r;
    scanf("%d",&n);
    k = ceil(log(n)/log(2));
    int pos = (1<<k);
    int a[n];
    for(int i=0;i<n;i++){
        scanf("%d",&temp);
        tree[pos+i] = node(temp);
        update(pos+i);
    }
    int m,c;

    scanf("%d",&m);
    while(m--)
    {
        scanf("%d%d%d",&c,&l,&r);
        if(c==1)
            printf("%d\n",(range_query(1,1,pos,l,r)).result);
        else if(c==0)// Update part-> remove this condition for GSS1.
        {
            tree[pos+l-1] = node(r);
            update(pos + l -1);
        }
    }
    return 0;
}