JAVA solution :
\n# Approach\nBinary Indexed Tree (BIT) Implementation:\n\n-  The BIT class provides methods for updating, querying, and clearing the BIT values.\n\nWrapper Fun
![image.png](https://assets.leetcode.com/users/images/60b1c367-00da-46fa-a3e2-086d351a19ed_1722745512.1602213.png)\n# Approach\n**Binary Indexed Tree (BIT) Implementation:**\n\n-  The BIT class provides methods for updating, querying, and clearing the BIT values.\n\n**Wrapper Functions:**\n\n- edt updates the BIT values.\n- qry queries the BIT values.\n\n**Length Calculation Functions:**\n\n- len calculates the length between two indices or a pair of indices.\n\n**Main Solution Class:**\n\n- The numberOfAlternatingGroups method processes the queries and updates the alternating groups efficiently.\n- A TreeMap is used to store the start and end indices of alternating groups.\n- For each query, the BITs are updated or queried as needed.\n<!-- Describe your approach to solving the problem. -->\n\n\n\n# Code\n```\nimport java.util.*;\n\nclass Solution {\n    private static final int SZ = 63333;\n    private static final int OFFSET = SZ - 10;\n\n    // Class to represent the Binary Indexed Tree (BIT)\n    static class BIT {\n        int[] bs = new int[SZ];\n\n        // Update BIT: add value y to index x\n        void update(int x, int y) {\n            x = OFFSET - x;\n            for (; x < SZ; x += x & -x) {\n                bs[x] += y;\n            }\n        }\n\n        // Query BIT: get the prefix sum up to index x\n        int query(int x) {\n            x = OFFSET - x;\n            int ans = 0;\n            for (; x > 0; x -= x & -x) {\n                ans += bs[x];\n            }\n            return ans;\n        }\n\n        // Clear BIT values up to index x\n        void clear(int x) {\n            x = OFFSET - x;\n            for (; x < SZ; x += x & -x) {\n                bs[x] = 0;\n            }\n        }\n    }\n\n    static BIT[] B = { new BIT(), new BIT() };\n\n    // Wrapper functions for updating and querying the BITs\n    static void edt(int x, int y) {\n        B[1].update(x, x * y); // Update second BIT with product of index and value\n        B[0].update(x, y);     // Update first BIT with value\n    }\n\n    static int qry(int x) {\n        return B[1].query(x) + (1 - x) * B[0].query(x); // Query BITs and combine results\n    }\n\n    // Function to calculate the length between two indices\n    static int len(int x, int y) {\n        return y - x + 1;\n    }\n\n    // Overloaded function to calculate length for a pair\n    static int len(Map.Entry<Integer, Integer> s) {\n        return len(s.getKey(), s.getValue());\n    }\n\n    // Main function to handle the queries\n    public List<Integer> numberOfAlternatingGroups(int[] colors, int[][] queries) {\n        TreeMap<Integer, Integer> C = new TreeMap<>(); // Map to store start and end indices of alternating groups\n        int n = colors.length;\n\n        // Initialize alternating groups\n        for (int i = 0; i < colors.length; ++i) {\n            int r = i;\n            // Find end of the current alternating group\n            while (r < colors.length && (colors[r] + colors[i] + r + i) % 2 == 0) {\n                ++r;\n            }\n            C.put(i, r - 1); // Store group boundaries in map\n            edt(r - i, 1); // Update BITs with new group\n            i = r - 1;     // Move to the end of the current group\n        }\n\n        List<Integer> results = new ArrayList<>(); // List to store results for type 1 queries\n\n        // Process each query\n        for (int[] q : queries) {\n            if (q[0] == 1) { // Query type 1: Count alternating groups of a given size\n                int ans = qry(q[1]);\n                Map.Entry<Integer, Integer> A = C.firstEntry(), B = C.lastEntry();\n                if (A != B) {\n                    // Check if merging groups is possible\n                    if (colors[0] != colors[colors.length - 1]) {\n                        int l1 = len(A.getKey(), A.getValue());\n                        int l2 = len(B.getKey(), B.getValue());\n                        ans -= Math.max(l1 - q[1] + 1, 0); // Subtract groups that are too small\n                        ans -= Math.max(l2 - q[1] + 1, 0);\n                        ans += Math.max(l1 + l2 - q[1] + 1, 0); // Add merged group size\n                    }\n                } else if (colors[0] != colors[colors.length - 1]) {\n                    ans = n; // If there\'s only one group, check if it can span the entire array\n                }\n                results.add(ans); // Store result for type 1 query\n            } else { // Query type 2: Update color at a given index\n                int x = q[1], y = q[2];\n                if (colors[x] == y) {\n                    continue; // If color is already correct, skip update\n                }\n                colors[x] = y; // Update color\n                // Find the block containing index x\n                Map.Entry<Integer, Integer> it = C.floorEntry(x);\n                assert it != null && it.getKey() <= x && it.getValue() >= x;\n                int L = it.getKey(), R = it.getValue();\n                edt(len(it.getKey(), it.getValue()), -1); // Remove the old block\n                C.remove(it.getKey());\n                int ML = x, MR = x;\n                // Update or split the affected blocks\n                if (L != ML) {\n                    C.put(L, x - 1);\n                    edt(len(L, x - 1), 1);\n                } else {\n                    if (x > 0 && colors[x] != colors[x - 1]) {\n                        it = C.floorEntry(x - 1);\n                        if (it != null) {\n                            ML = it.getKey();\n                            edt(len(it.getKey(), it.getValue()), -1);\n                            C.remove(it.getKey());\n                        }\n                    }\n                }\n                if (R != MR) {\n                    C.put(x + 1, R);\n                    edt(len(x + 1, R), 1);\n                } else {\n                    if (x + 1 < colors.length && colors[x + 1] != colors[x]) {\n                        it = C.ceilingEntry(x + 1);\n                        if (it != null) {\n                            MR = it.getValue();\n                            edt(len(it.getKey(), it.getValue()), -1);\n                            C.remove(it.getKey());\n                        }\n                    }\n                }\n                C.put(ML, MR);\n                edt(len(ML, MR), 1); // Add new or modified block\n            }\n        }\n\n        // Clear BITs after processing all queries\n        for (int i = 0; i <= n + 2; ++i) {\n            B[0].clear(i);\n            B[1].clear(i);\n        }\n\n        return results; // Return results for type 1 queries\n    }\n  \n}\n\n```
['Java']