// #include<bits/stdc++.
h>
// using namespace std;
// int main(){
// ///PAIR
// // pair<int,string> p;
// // //initialization
// //firstway// p=make_pair(2,"swapnil");
// //secondway// p={2,"swapnil"};
// // cout<<p.first<<" "<<p.second<<endl;
// // int a[]={1,2,3};
// // int b[]={2,3,4};
// // pair<int,int> p_array[3];
// // //basically this can be seen as this is array of pairs //remember normally we declared array
by firstly writing the datatype of array then the name followed by name here too similar syntax could
be seen as firstly there is pair<int,int> which is kind of datatype telling about the data and then the
array name then the size
// // p_array[0]={1,2};
// // p_array[1]={2,3};
// // p_array[2]={3,4};
// // for(int i=0;i<3;i++)
// // {
// // cout<<p_array[i].first<<" "<<p_array[i].second;
// // }
// //VECTORS
// return 0;
// }
// VECTORS
// #include <bits/stdc++.h>
// using namespace std;
// void printVec(vector<int> v)
// {
// cout << "size:" << v.size() << endl;
// for (int i = 0; i < v.size(); i++)
// {
// // v.size-->O(1)
// cout << v[i] << " ";
// }
// cout << endl;
// }
// int main()
// {
// // 1// vector<int> v;
// // int n;
// // cin >> n;
// // for (int i = 0; i < n; i++)
// // {
// // int x;
// // cin >> x;
// // printVec(v);
// // v.push_back(x);
// // 1//}
// // declaration
// vector<int> v(10, 3);
// v.push_back(7); // firstly we had our vector or dynamic array of size 10 and each element was 3
and so the current size after this is 10 and in next line we add another element 7 which is the 11th
element so you can see we need not care about the size it changes dynamically according to the
need of the program
// printVec(v);
// v.pop_back(); // this function removes the last element
// printVec(v);
// // another good thing about vector is we directly copy the elements from one to another vector
by directly assigning as we used to do in variables
// // And this was not possible in array and haa this operation in the background uses the same
thing we used to do while copying an array to another using for loop so the time complexity is O(n)
// vector<int> v2 = v;
// // v2 is a whole different vector whose element are the same as that of v
// v.pop_back(); // we have made changes in v and lets see does this affect v2 which obviously will
not affect v2 so which means v2 is different vector
// printVec(v);
// printVec(v2);
// // we can have vectors of not all data types and even of containers like vectors of pairs or
vectors of vector
// return 0;
// }
// NESTING OF VECTORS
// vector of pairs
// #include <bits/stdc++.h>
// using namespace std;
// void printVec(vector<pair<int, int>> v)
// {
// cout << "size:" << v.size() << endl;
// for (int i = 0; i < v.size(); i++)
// {
// // v.size-->O(1)
// cout << v[i].first << " " << v[i].second<<endl;
// }
// cout << endl;
// }
// int main()
// {
// // vector<pair<int, int>> v = {{1, 2}, {2, 3}, {3, 4}};
// // printVec(v);
// vector<pair<int,int>> v;
// printVec(v);
// for (int i = 0; i < v.size(); i++)
// {
// int x,y;
// cin>>x>>y;
// v.push_back({x,y}); //v.pushback(make_pair(x,y)) this is another way of writing the pair
// }
// printVec(v);
// }
// array of vectors
// #include<bits/stdc++.h>
// using namespace std;
// void printVec(vector<int> v)
// {
// cout << "size:" << v.size() << endl;
// for (int i = 0; i < v.size(); i++)
// {
// // v.size-->O(1)
// cout << v[i]<<" ";
// }
// cout << endl;
// }
// int main(){
// int N;
// cin>>N;
// vector<int> v[N];
// for(int i=0;i<N;i++)
// {
// int n;
// cin>>n;
// for(int j=0;j<n;j++)
// {
// int x;
// cin>>x;
// v[i].push_back(x);
// }
// }
// for(int i=0;i<N;i++)
// {
// printVec(v[i]);
// }
// //basically this array of vectors behave as 2D vectors in which nmber of rows is fixed and length
of rows or length of vector or no of column of each row is varying
// return 0;
// }
// vectors of vectors
// #include<bits/stdc++.h>
// using namespace std;
// void printVec(vector<int> v)
// {
// cout << "size:" << v.size() << endl;
// for (int i = 0; i < v.size(); i++)
// {
// // v.size-->O(1)
// cout << v[i]<<" ";
// }
// cout << endl;
// }
// int main(){
// vector<vector<int>> v;
// int N;
// cin>>N;
// for(int i=0;i<N;i++)
// { int n;
// cin>>n;
// //2.// vector<int> temp; //we have used a temporary vector as oonly the vector v is
initialized which has vector elements and thus we can add the vector element and not add the
elements of this vector as initially only the vector of vector element is initiallized and not the internal
each vector
// //.1// v.push_back(vector<int>()); //this adds vector element and now we can directly add
element of the vector element
// for(int i=0;i<n;i++) //instead of dummy temp we could have inserted a empty vector then we
have accessed the vector v[i] as now we have created a vector which earlier did not exist
// {
// int s;
// cin>>s;
// //2.// temp.push_back(s);
// //1.//v[i].push_back(s); as now v[i] exists after doing the above //.1// thing
// }
// v.push_back(temp);
// }
// for(int i=0;i<N;i++){
// printVec(v[i]);
// }
// return 0;
//}
// Iterators
// they point to the elements of the container it is like pointers only
// iterator pointing to the first element is the vectorname.begin() iterator and the one pointing to
the hypothetical element just after the last element is the vectorname.end() iterator
// we can iterate through elements of any container using these iterators . Also vectors have array
like indices which is very useful in accessing elements but in other containers this indices system is
not there so here comes the main role of iterators
// #include <bits/stdc++.h>
// using namespace std;
// // int main(){
// vector<int> v={2,3,4,5,6};
// for(int i=0;i<v.size();i++)
// {
// cout<<v[i]<<endl;
// }
// //initialization of iterators
// vector<int> ::iterator it =v.begin();
// //accessing using iterators
// for(it = v.begin();it!=v.end();it++)
// {
// cout<<*it<<endl;
// }
// }
// iterators in pairs
// int main(){
// vector<pair<int, int>> v_p={{1,2},{2,3},{3,4}};
// vector<pair<int,int>> ::iterator it;
// for(it =v_p.begin();it!=v_p.end();++it)
// {
// cout<<(*it).first<<" "<<(*it).second<<endl; //you can visualize like it points to the pair
address and *it points to the pair value as a whole just like pair name used to do so similar thing can
be done to access the pair element like we used to do pairname.first and now we do *it.first
// }
// //in case of pairs we have another syntax for accesssing its elements like so lets to we rewrite the
above forloop according to the new syntax
// //basically (*it).first === (it->first)
// for(it =v_p.begin();it!=v_p.end();++it)
// {
// cout<<(it->first)<<" "<<(it->second)<<endl;
// }
// }
// writing short codes in iterators
// writing range based loops
// int main()
// {
// // vector<int> v = {1, 2, 3, 4};
// for (int i = 0; i < v.size(); ++i)
// {
// cout << v[i] << " ";
// }
// cout << endl;
// vector<int>::iterator it;
// for(it=v.begin();it!=v.end();it++){
// cout<<(*it)<<" ";
// }
// 1.//// for (int value : v) // so here what happens is value me every element ka copy goes then does
the work with it then moves to the next element toh if we make changes in the elements by writing
some code in the if block then it wont change the element in the vector
// { // but if we want changes in the value by the code written in the forloop then we need
to use reference operator in the for loop bracket
// cout << value << " ";
// value++; //though we have written this we will not see any changes in the elements of the
vectors which can seen in the next for loop as this step make changes in the copy which is taken from
each element of vector in each iteration
// }
// cout << endl;
// for (int value : v)
// {
// cout << value << " ";
// }
// cout << endl;//1.//
// 2.//for (int &value : v)
// {
// value++; //this value ++ will make changes in the actual vector and then if now print the
element of the vector then we can see the changes
// }
// for (int value : v)
// {
// cout << value << " ";
// }
// cout << endl;//2.//
// using range forloops for pairs
// vector<pair<int, int>> v_p = {{1, 2}, {2, 3}, {3, 4}};
// for (pair<int, int> value : v_p)
// {
// cout << value.first << " " << value.second;
// cout << endl;
// }
// }
// using auto for initialization of iterators
// auto dynamically declares the data types of the variable or containers based on the input value
stored in it
// vector<int> v = {1, 2, 3, 4};
// 1 // vector<int>::iterator it;
// for (it = v.begin(); it != v.end(); it++)
// {
// cout << (*it) << " ";
// }
// cout << endl;
// 1 ka alternative // for (auto itt = v.begin(); itt != v.end(); itt++) //here you can see that wo iterator
ke liye wo bada sa pehle likho ki kaunsa data type ya container ka wo iterator hai phir uska naam isse
acha bina ye line likhe seedhe for ke ander auto aur phir iterator ka naam = to the value lets say
v.begin() here aur bas ye auto does the work for the declaration too
// {
// cout << (*itt) << " ";
// }//
// using auto in range for loops used to access elements of vectors of pairs
// 2//
// vector<pair<int, int>> v_p = {{1, 2}, {2, 3}, {3, 4}};
// for (pair<int, int> value : v_p)
// {
// cout << value.first << " " << value.second;
// cout << endl;
// }
// //just upar wale for loop ka alternative using auto which shortens the code to a much extent
// for (auto value : v_p) //ye auto khudse hi based on elements dekhlega ki v_p vectors ke
elements kya hai pairs hai toh wo automatically pairs pe set hojayega
// {
// cout << value.first << " " << value.second;
// cout << endl;
// }
// }
/// MAPS
// void print(map<int, string> m)
// {
// cout << m.size() << endl;
// for (auto &value : m) //& se yaad hai na kya hoga agar ye nahi hota toh har element ki copy jaa
rahi hoti in the value container ab wo reference operator ke wajah se wo element hi direct jayega
this crude way of saying but this is what it is
// {
// cout << value.first << " " << value.second << endl;
// }
// }
// int main()
// {
// // initialization of maps
// map<int, string> m;
// m[1] = "abc"; // bracket me key hai //aur haa ye likhne that is step jisme ham key insert kar rahe
hai isi ka time complexity is O(logn)where n is the size of the map aur tum lets say m[i] karke kuch
value na assign karo toh bhi itna time complexity lagega like agar value ka datatype int hai toh value
automatically 0 aur agr string hai toh zero string apne aap hi dal jayega
// m[5] = "cdc";
// m[3] = "acd";
// m.insert({4, "afg"}); // another way to add element in a map
// map<int, string>::iterator it;
// for (it = m.begin(); it != m.end(); it++)
// {
// cout << (*it).first << " " << (*it).second << endl; // output you see the result is printed in a sorted
way like even though i have given 5 as input in the second time then too it printed this key value pair
last as this normal maps prints things in sorted order
// }
// for (auto itt = m.begin(); itt != m.end(); itt++)
// {
// cout << (*itt).first << " " << (*itt).second << endl;
// }
// using functions of maps
// 11// auto it=m.find(4);
// if(it==m.end())
// {cout<<"No value";}
// else{
// cout<<(*it).first<<" "<<(*it).second;
// }
// 222//
// auto it = m.find(7);
// 23// m.erase(it); //gives error or absurd output as it iterator does not exist or we can say points to
a location where no element is there so this happens so it is always a good habbit to use if(it!
=m.end()) and then proceed the code like in the following way
// 23 betterway// if (it != m.end())
// {
// m.erase(it);
// }
// 23//
// print(m);
// 123//
// another function is clear() function
// }
// UNordered Maps
// void print(unordered_map<int, string> &m)
// {
// cout << m.size() << endl;
// for (auto value : m)
// {
// cout << value.first << " " << value.second << endl;
// }
// }
// int main()
// {
// // everything is same in unordered maps and normal maps just that while initializiing you write
unordered maps
// unordered_map<int, string> m;
// m[1] = "abc";
// m[5] = "cdc";
// m[3] = "acd";
// m[6] = "a";
// m[5] = "cde";
// print(m);
// }
#include <bits/stdc++.h>
using namespace std;
void print(set<string> s)
for (string value : s)
cout << value << endl;
// for (auto it = s.begin(); it != s.end(); it++) // we can use this for loop also to print the elements
but prefer first one as that is small and preferred by most programmers
// {
// cout << (*it) << endl;
// }
int main()
set<string> s;
s.insert("abc");
s.insert("zsdf");
s.insert("bcd");
// print(s);
auto it = s.find("abcd");
if (it != s.end()) /// this is done to avoid segmentation fault as lets say if we try to find element
which is not there in the set then this iterator will be alloted the s.end() iterator and dereferencing
this iterator may lead to undefined behaviour as this iterator points to an unallocated memory where
there is no element stored
cout << (*it);
// lets say i again insert the element which is already there in the set then it will not be stored as
like maps sets also stores unique keys just that here there is only keys and not values
// same as maps here also we have erase() function which erase an element and this takes iterator
as input and also directly takes the keys also which needs to be deleted from the set
return 0;