#include <bits/stdc++.h> // Includes common standard libraries like iostream, map, string, utility.
using namespace std; // Use the standard namespace.
// --- Creation of a map ---
// Declares a map named 'M' where keys are of type 'string' and values are of type 'int'.
// --- Insertion of elements ---
// Method 1: Using std::pair and insert()
// Creates a pair and inserts it into the map.
pair<string, int> pair1 = make_pair("white", 2);
M.insert(pair1); // M now: {"white": 2}
// Method 2: Creating a pair directly in insert()
// Another way to create and insert a pair.
pair<string, int> pair2("black", 3);
M.insert(pair2); // M now: {"black": 3, "white": 2} (Keys are sorted, so "black" comes before "white")
// Method 3: Using array-like subscript operator []
// This is often the most concise way. If "red" doesn't exist, it's inserted.
// If it exists, its value would be updated.
M["red"] = 4; // M now: {"black": 3, "red": 4, "white": 2}
// --- Accessing and Updating Elements ---
// Accessing an existing element using []
cout << "Before updation : white = " << M["white"] << endl; // Output: 2
// Updation: Using [] to change the value associated with an existing key.
cout << "After updation : white = " << M.at("white") << endl; // Output: 10
// Using .at() is safer for lookup as it throws std::out_of_range if key not found.
// Behavior of [] vs .at() for non-existent keys:
// The commented line below would throw an std::out_of_range exception because "orange" does not exist.
// cout << M.at("orange") << endl;
// Using [] for a non-existent key will *insert* the key with a default-constructed value (0 for int).
// This can be a side effect to be aware of.
cout << "Value of non-existent key 'orange' using []: " << M["orange"] << endl; // Output: 0 (and inserts {"orange": 0})
// M now: {"black": 3, "orange": 0, "red": 4, "white": 10}
// --- Size of the map ---
cout << "Size : " << M.size() << endl; // Output: 4
// --- Checking presence of a key ---
// .count(key) returns 1 if key exists, 0 otherwise (since keys are unique).
cout << "Is 'yellow' present? (0=No, 1=Yes) : " << M.count("yellow") << endl; // Output: 0
cout << "Is 'white' present? (0=No, 1=Yes) : " << M.count("white") << endl; // Output: 1
// --- Removal of elements ---
M.erase("white"); // Removes the element with key "white".
cout << "Size after erasing 'white' : " << M.size() << endl; // Output: 3
// M now: {"black": 3, "orange": 0, "red": 4}
// --- Traversal (Iterating through the map) ---
// Using a range-based for loop (C++11 and later) - very convenient.
// Elements are iterated in sorted order of keys.
cout << "Elements in map after removal (sorted by key):" << endl;
cout << i.first << " & " << i.second << endl;
// --- Iterator-based Traversal (Alternative, more traditional way) ---
// Uncomment this block to see iterator-based traversal.
// map<string, int> :: iterator it = M.begin(); // Get an iterator to the first element.
// while(it != M.end()) { // Loop until the iterator reaches the end of the map.
// cout << it->first << " , " << it->second << endl; // Access key (first) and value (second) using ->
// it++; // Move to the next element.
// Note: The commented code block uses 'unordered_map' iterator type, but 'map' iterators work the same way.
// If you uncommented, change `unordered_map<string, int> :: iterator it = M.begin();`
// to `map<string, int> :: iterator it = M.begin();`
return 0; // Indicate successful execution.