Getting tle in Flipping coin even though used segment trees

import java.util.*;

import java.io.*;

public class Main {

static class node

{

   int head;

   int tail;

    // use more variables if you want more information

    // these default values should be identity_element

    node(){}

    node(int head, int tail){

        this.head = head;

        this.tail = tail;

    }

    void merge( node l,node r){ // store the thing you wanna query

        

        // mn = Math.min(l.mn,r.mn);

        // freq = 0;

        // if(l.mn == mn) freq += l.freq;

        // if(r.mn == mn) freq += r.freq;

        head = l.head + r.head;

        tail = l.tail + r.tail;

        

        // if we wanted the maximum, then we would do

        // like v = max(l.v,r.v)

    }

}

// example: add on a range: identity transformation = 0

// old += new

// if old is identity which is 0, then 0 + new which new

static class update

{

int no_of_flip = 0; // 4

// use more variables if you want more information

// these default values should be identity_transformation

update(){}

update(int val){

    no_of_flip = val; // 5

}

// combine the current my_update with the other my_update (see keynotes)

void combine(update other,int tl,int tr){

     no_of_flip += other.no_of_flip; // 6



    // you can be sure that the "other" is newer than current



}

// store the correct information in the my_node x

void apply(node x,int tl,int tr){



    // int temp_head = x.head;

    int temp_tail = x.tail;

    if(no_of_flip % 2 != 0)

    {

        x.tail = x.head;

        x.head = temp_tail;

    }



}

}

static class segtree

{

    int len;

    node t[];

    update u[];

    boolean []lazy;

    node identity_element;

    update identity_transformation;

    segtree(int l){

        len = l;

        t = new node[4 * len + 1];

        u = new update[4 * len + 1];

        lazy = new boolean[4 * len + 1];

        identity_element = new node();

        identity_transformation = new update();

    }

 

    void pushdown(int v, int tl, int tr){

        if(!lazy[v]) return;

        int tm = (tl + tr) >> 1;

        apply(v<<1,tl,tm,u[v]);

        apply(v<<1|1,tm+1,tr,u[v]);

        u[v] = identity_transformation;

        lazy[v] = false;

    }

 

    void apply( int v,  int tl,  int tr, update upd){

        if(tl != tr){

            lazy[v] = true;

            u[v] = new update(0);

            u[v].combine(upd,tl,tr);

        }

        upd.apply(t[v],tl,tr);

    }

    void build( int[] arr, int v,  int tl,  int tr){

        if(tl == tr){

            t[v] = new node(0,1);

            return;

        }

        int tm = (tl + tr) >> 1;

        build(arr,v<<1,tl,tm);

        build(arr,v<<1|1,tm+1,tr);

        t[v] = new node(0,0);

        t[v].merge(t[v<<1],t[v<<1|1]);

    }

 

    node query( int v, int tl, int tr, int l, int r){

        if(l > tr || r < tl){

            return identity_element;

        }

        if(tl >= l && tr <= r){

            return t[v];

        }

        pushdown(v,tl,tr);

        int tm = (tl + tr) >> 1;

        node a = query(v<<1,tl,tm,l,r);

        node b = query(v<<1|1,tm+1,tr,l,r);

        node ans = new node();

        ans.merge(a,b);

        return ans;

    }

 

    // rupd = range update

    void rupd( int v, int tl, int tr, int l, int r, update upd){

        if(l > tr || r < tl){

            return;

        }

        if(tl >= l  &&  tr <= r){

            apply(v,tl,tr,upd);

            return;

        }

        pushdown(v,tl,tr);

        int tm = (tl + tr) >> 1;

        rupd(v<<1,tl,tm,l,r,upd);

        rupd(v<<1|1,tm+1,tr,l,r,upd);

        t[v].merge(t[v<<1],t[v<<1|1]);

    }

    void build( int[] arr){

        build(arr,1,0,len-1);

    }

    node query( int l, int r){

        return query(1,0,len-1,l,r);

    }

    void rupd( int l, int r, update upd){

        rupd(1,0,len-1,l,r,upd);

    }

}

public static void main(String[] args) throws IOException   {

    try{

    Scanner sc =  new Scanner(System.in);

    int n = sc.nextInt();

    int q = sc.nextInt();

    int [] arr = new int[n];

    // int max = 0;

    // for(int i = 0;i<n;i++)

    // {

    //     arr[i] = sc.nextInt();

    //     max = Math.max(max, arr[i]);

    // }

    int ans = 0;

    segtree s =  new segtree(n);

    s.build(arr);

    while(q > 0)

    {

        int type,x,y;

        type = sc.nextInt();

        x = sc.nextInt();

        y = sc.nextInt();

        if(type == 0)

        {

            s.rupd(x, y , new update(1));

        }

        else if(type == 1){

            System.out.println(s.query(x, y ).head);

        }

        q--;

    }

    // int []arr =  new int[1000];

    // arr[10] = 35;

    // arr[13] = 3;

    // s.build(arr);

    // s.rupd(2, 5, new update(8));

    // s.rupd(1,3,new update(-4));

    // System.out.print(s.query(2, 4).mn44);

    // System.out.print(ans);

    

    // sc.close();

    return;

    }

    catch(Exception e)

    {

        return;

    }

        

}

}