You are given an array of events where events[i] = [startDayi, endDayi]. Every event i starts at startDayi and ends at endDayi.

You can attend an event i at any day d where startTimei &lt;= d &lt;= endTimei. You can only attend one event at any time d.

Return the maximum number of events you can attend.

&nbsp;
Example 1:

Input: events = [[1,2],[2,3],[3,4]]
Output: 3
Explanation: You can attend all the three events.
One way to attend them all is as shown.
Attend the first event on day 1.
Attend the second event on day 2.
Attend the third event on day 3.


Example 2:

Input: events= [[1,2],[2,3],[3,4],[1,2]]
Output: 4


&nbsp;
Constraints:


	1 &lt;= events.length &lt;= 105
	events[i].length == 2
	1 &lt;= startDayi &lt;= endDayi &lt;= 105


class Solution(object):
    def maxEvents(self, events):
        """
        :type events: List[List[int]]
        :rtype: int
        """
        events = sorted(events, key=lambda x: x[0])
        current_day = 0
        min_heap = []
        event_id = 0
        total_number_of_days = max(end for start, end in events)
        total_events_attended = 0
        #total_number_of_days+1 because I want to include the last day
        for day in range(1, total_number_of_days+1):

            #Add all the events that can be started on that day
            while event_id < len(events) and events[event_id][0] == day:
                heapq.heappush(min_heap, events[event_id][1])
                event_id+=1

            #while there is something in heap and the event should have been completed before the current day
            #remove those evenets and consider them not attended
            while min_heap and min_heap[0] < day :
                heapq.heappop(min_heap)

            #if theere is an event present in heap
            #lets mark 1 of those events as complted today and add it to
            #total_events_attended

            if min_heap:
                heapq.heappop(min_heap)
                total_events_attended+=1
        return total_events_attended
class Solution {
    public int maxEvents(int[][] events) {
        Arrays.sort(events,(a,b)->a[1]==b[1]?a[0]-b[0]:a[1]-b[1]);
        // here sorting the array on ths basis of last day because we want to finish the events which happens first,fist.
        
 TreeSet<Integer> set =new TreeSet<>();
        for(int i =1;i<=100000;i++){
            set.add(i);
        }
        //initliasing a tree set to check available days ;
        // a day can go maximum to 100000;
        int ans =0;
        for(int i =0;i<events.length;i++){
         Integer  temp = set.ceiling(events[i][0]);
            if(temp==null || temp >events[i][1])
                continue;
            else{
                set.remove(temp);
            ans +=1;
            }
        }
        return ans;        
    }
}
class Solution {
public:
    int maxEvents(vector<vector<int>>& events) {
        int res=0;
        int m=0;
        for(auto x:events)
            m=max(m,x[1]);

        sort(events.begin(),events.end());
        int j=0;
        priority_queue<int,vector<int>,greater<int>> pq;
        for(int i=1;i<=m;i++)
        {
            while(!pq.empty() && pq.top()<i)// end day is less than the current day
                pq.pop();

            while(j<events.size() && events[j][0]==i)// put all events start at day i
                pq.push(events[j++][1]);

            if(!pq.empty())// we can attend an event today
            {
                pq.pop();// remove the event
                res++;// count that event
            }
        }
        return res;
    }
};
/**
* O(nlogn)
*/
var maxEvents = function(events) {

    // sort events by their start time
    events.sort((a,b) => a[0]-b[0]);

    // create priority queue to sort events by end time, the events that have saem start time
    let minHeap = new PriorityQueue((a, b) => a - b);
    let i = 0, len = events.length, res = 0, d = 0;

    while(i < len || !minHeap.isEmpty()){

        if (minHeap.isEmpty())
            d = events[i][0]; // start with event from events list

        while (i < len && events[i][0] <= d) // Add all events that have start time <= day `d` into PQ
            minHeap.add(events[i++][1]); // add ending time to the minHeap, so when we pull we get event that is ending first

        minHeap.poll(); // make sure we have some event attent
        ++res;
        ++d;

        // we finished task of day 'd' Remove events that are already closed ie endTime < d as we cant attend it
        while (!minHeap.isEmpty() && minHeap.peek() < d)
            minHeap.poll();
    }
    return res;
};

/*******************standard priority queue implementation used in all leetcode javascript solutions****************/
class PriorityQueue {

    /**
    * Create a Heap
    * @param {function} compareFunction - compares child and parent element
    * to see if they should swap. If return value is less than 0 it will
    * swap to prioritize the child.
    */
    constructor(compareFunction) {
        this.store = [];
        this.compareFunction = compareFunction;
    }

    peek() {
        return this.store[0];
    }

    size() {
        return this.store.length;
    }
    isEmpty() {
        return this.store.length === 0;
    }

    poll() {
        if (this.size() < 2) {
            return this.store.pop();
        }
        const result = this.store[0];
        this.store[0] = this.store.pop();
        this.heapifyDown(0);
        return result;
    }

    add(val) {
        this.store.push(val);
        this.heapifyUp(this.size() - 1);
    }

    heapifyUp(child) {
        while (child) {
            const parent = Math.floor((child - 1) / 2);

            if (this.shouldSwap(child, parent)) {
                [this.store[child], this.store[parent]] = [this.store[parent], this.store[child]]
                child = parent;
            } else {
                return child;
            }
        }
    }

    heapifyDown(parent) {
        while (true) {
            let [child, child2] = [1,2].map((x) => parent * 2 + x).filter((x) => x < this.size());
            if (this.shouldSwap(child2, child)) {
                child = child2;
            }

            if (this.shouldSwap(child, parent)) {
                [this.store[child], this.store[parent]] = [this.store[parent], this.store[child]]
                parent = child;
            } else {
                return parent;
            }
        }
    }

    shouldSwap(child, parent) {
        return child && this.compareFunction(this.store[child], this.store[parent]) < 0;
    }
}
Maximum Number of Events That Can Be Attended