蓝桥杯C++
一、语言基础
1.1 编程基础
#include<bits/stdc++.h>
using namespace std;int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);return 0;
}
#include<bits/stdc++.h>
using namespace std;typedef long long ll;const int N=1e5+9;//const表示常量,后续不能被改变,1e+9为10的5次方加9
ll a[N];//开一个大小为N的全局数组,下标为[0,N-1],自动初始化为0,如果放在main里面变成未知int main(){//取消同步流ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); return 0;
}
输入输出
scanf和printf
int main(){char s[15];scanf("%[^\n]",s);//读到回车结束,遇到空格也继续;^:排除printf("%s",s);return 0;
}
cin和cout
#include <iostream>
#include <iomanip>
using namespace std;int main(){double a,b;cin>>a>>b;cout<<fixed<< setprecision(3)<<a<<' '<<b<<'\n';//'\n'比endl更快一些
//2.000 3.000return 0;
}
int main(){char s[10];cin>>s;cout<<s<<endl;//lanreturn 0;
}
int main(){string s;cin>>s;cout<<s;//lanreturn 0;
}
#include<string>
int main(){string s;getline(cin,s);cout<<s;//lan qiaoreturn 0;
}
取消同步流
#include<bits/stdc++.h>
using namespace std;
int main(){//取消同步流ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); //其他操作不变int x;cin>>x;cout<<x; return 0;
}
string
声明与初始化
#include<bits/stdc++.h>
using namespace std;int main(){string str1;string str2="Hello World";string str3=str2;string str4=str2.substr(0,5);const char* charA="Hello";string str5(charA);string str6(5,'A');string str7=str2.substr(0);getline(cin,str1);cout<<str1<<endl;cout<<str2<<endl;cout<<str3<<endl;cout<<str4<<endl;cout<<str5<<endl;cout<<str6<<endl;cout<<str7<<endl;return 0;
}
各种基本操作
转换为C风格
std::string 类提供成员函数c_str()用于返回一个以空字符结尾的C风格字符串,即const char * 类型
#include<bits/stdc++.h>
using namespace std;int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);char buf[100];scanf("%s",buf);string str(buf);printf("str=%s\n",str.c_str());return 0;
}
获取字符串长度
string str="Hello";
int length1=str.length();
int length2=str.size();
cout<<"字符串的长度为:"<<length<<endl;
拼接字符串
string str1="Hello";
string str2="World!";
string result1=str1+","+str2;
string result2=str1.append(",").append(str2);
字符串查找
string str="Hello,World!";
size_t pos=str.find("World");//查找子字符串的位置
if(pos!=string::npos){cout<<"Substring found at position:"<<pos<<endl;
}else{cout<<"Substring not found."<<endl;
}
字符串替换
string str ="Hello,World!";
str.replace(7,5,"Universe");//替换子字符串
cout<<"Result:"<<str<<endl;
提取子字符串长度
string str="Hello,World";
string subStr=str.substr(7,5);
cout<<subStr<<endl;
字符串比较
string str1="Hello";
string str2="World";
int result=str1.compare(str2);
if(result==0){cout<<"Strings are equal."<<endl;
}else if (result<0){cout<<"String 1 is less than String 2."<<endl;
}else {cout<<"String 1 is greater than String 2."<<endl;
}
从第一个开始比较:aaaa<bbbb azz<baaa azzzzz<b
遍历字符串
(1)循环枚举下标
(2)auto枚举(&表示取引用类型,对i修改会改变原来的值)
string s="Hello";for(int i=0;i<s.length();i++)cout<<s[i];//Hellocout<<endl;for(auto i:s){cout<<i;//Helloi='a';}cout<<'\n';for(auto &i:s){cout<<i;//Helloi='a';}cout<<"\n";cout<<s<<'\n';//aaaaa
反转字符串中的字符
#include<bits/stdc++.h>
using namespace std;
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);string s;getline(cin,s);for(int i=(int)s.length()-1;i>=0;i--){cout<<s[i];}return 0;
}
string s;getline(cin,s);reverse(s.begin(),s.end());cout<<s<<'\n';
string s;
getline(cin,s);
for(int i=0;i<s.length()/2;i++)swap(s[i],s[s.length()-i-1]);
cout<<s<<'\n';
1.2 常用库函数
排序
*sort函数
sort算法时间复杂度为O(nlogn),sort(起始地址,结束地址的下一位,*比较函数),比较函数可有可无,默认为<
int a[1000];int n;cin>>n;for(int i=0;i<n;i++)cin>>a[i];sort(a,a+n);
//左闭右开a[0,n)for(int i=0;i<n;i++)cout<<a[i]<<' ';
vector<int>v={5,1,3,9,11};sort(v.begin(),v.end());for(int i=0;i<v.size();i++) cout<<v[i]<<' ';cout<<'\n';for(auto i:v)cout<<i<<' ';
自定义比较函数
bool cmp(int u,int v){return u>v;
}int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);vector<int>v={5,1,3,9,11};sort(v.begin(),v.end(),cmp);for(int i=0;i<v.size();i++) cout<<v[i]<<' ';cout<<'\n';for(auto i:v) cout<<i<<' ';return 0;
}
lambda表达式:无需单独定义函数,函数只使用一次
vector<int>v={5,1,3,9,11};sort(v.begin(),v.end(),[](int u,int v){return u>v;});for(int i=0;i<v.size();i++) cout<<v[i]<<' ';cout<<'\n';for(auto i:v) cout<<i<<' ';
例题:升序和降序对数组进行排序
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int a[N];int main(){int n;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];sort(a+1,a+n+1);for(int i=1;i<=n;i++)cout<<a[i]<<" \n"[i==n];for(int i=n;i>=1;i--)cout<<a[i]<<" \n"[i==1];return 0;
}
最值查找
min和max函数
min(3.5)=3 min({1,2,3,4})=1
min_element和max_element函数
min_element(st,ed)返回地址为[st,ed)中最小的那个值的地址(迭代器),传入参数为两个地址或迭代器。
//初始化v
vector<int> v = {5,1,3,9,11};//输出最大的元素,*表示解引用,即通过地址(迭代器)得到值
cout<< *max_element(v.begin(),v.end())<<'\n';
nth_element函数
进行部分排序,返回值为void
//初始化v
vector<int> v = {5,1,7,3,10,18,9};nth_element(v.begin(),v.begin()+3,v.end());for(auto &i : v)cout<<i<<' ';//3 1 5 7 9 18 10
例题:求数组的最值和平均值
#include<bits/stdc++.h>
using namespace std;using ll=long long;
const int N=1e4+9;
int a[N];int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int n;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];cout<<*max_element(a+1,a+n+1)<<'\n';cout<<*min_element(a+1,a+n+1)<<'\n';ll sum=0;for(int i=1;i<=n;i++)sum+=a[i];cout<<fixed<<setprecision(2)<<1.0*sum/n<<'\n';return 0;
}
二分查找
二分查找的前提
只能对数组,元素必须单调
binary_serch函数
是否存在目标元素
vector<int>numbers={1,3,5,7,9};int target=3;bool found=binary_search(numbers.begin(),numbers.end(),target);if(found){cout<<"found "<<target<<endl;}else{cout<<"not found "<<target<<endl;}
*lower_bound和upper_bound函数
数组必须为非降序
lower_bound(st,ed,x)返回[st,ed)中第一个大于等于x的元素的地址
upper_bound(st,ed,x)返回[st,ed)中第一个大于x的元素的地址
不存在则返回最后一个元素的下一个位置,在vector中即end()
vector<int> v={5,1,7,3,10,18,9};sort(v.begin(),v.end());for(auto &i:v)cout<<i<<' ';cout<<'\n';//找到数组中第一个大于等于8的元素的位置cout<<(lower_bound(v.begin(),v.end(),8)-v.begin())<<'\n'; //4
[lower_bound,upper_bound)
例题讲解
给定数组,查找目标元素在数组中的位置
//给定数组int data[200];for(int i=0;i<200;i++)data[i]=4*i+6;int target;cin>>target;cout<<(lower(data,data+200,target)-data)<<'\n';
大小写转换
islower/isupper函数
用于检查一个字符是否为小写字母或者大写字母,返回值为bool类型
char ch1='a';char ch2='A';if(islower(ch1)){cout<<ch1<<" is a lowercase letter."<<endl;}else{cout<<ch1<<" is not a lowercase letter."<<endl;}if(isupper(ch2)){cout<<ch2<<" is an uppercase letter."<<endl;}else{cout<<ch2<<" is not an uppercase letter."<<endl;}
tolower/toupper函数
tolower可以将ch转换为小写字母,如果ch不是大写字母则不进行操作。
char ch1='A';char ch2='b';char lowercase1=tolower(ch1);cout<<"Lowercase of "<<ch1<<" is "<<lowercase1<<endl;char uppercase2=toupper(ch2);cout<<"Uppercase of "<<ch2<<" is "<<uppercase2<<endl;
ascii码
0-9:48-57;A-Z:65-90;a-z:97-122.
#include<bits/stdc++.h>
using namespace std;char convertedCh(char ch){if('a'<=ch&&ch<='z')ch=ch-'a'+'A';else if ('A'<=ch&&ch<='Z') ch=ch-'A'+'a';return ch;
}int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);string s;getline(cin,s);for(auto &i:s)i=convertedCh(i);cout<<s<<'\n';return 0;
}
全排列
next_permutation()函数
用于生成当前序列的下一个排列。按字典序对序列:如果存在下一个排列,将当前序列更改为下一个排列,返回为true;如果已经是最后一个排列,将序列更改为第一个排列,返回为false。
123->132->213->231->312->321
vector<int>nums={1,2,3};cout<<"原排列:";for(int num:nums)cout<<num<<' ';cout<<endl;while(next_permutation(nums.begin(),nums.end())){cout<<"Next permutation: ";for(int num:nums){cout<<num<<' ';}cout<<endl;}
prev_permutation()函数
返回上一个排列
vector<int>nums={3,2,1};cout<<"原排列:";for(int num:nums)cout<<num<<' ';cout<<endl;while(prev_permutation(nums.begin(),nums.end())){cout<<"Previous permutation: ";for(int num:nums){cout<<num<<' ';}cout<<endl;}
数组
#include<bits/stdc++.h>
using namespace std;int a[10];int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);for(int i=1;i<=3;i++)a[i]=i;bool tag=true;while(tag){for(int i=1;i<=3;i++)cout<<a[i]<<' ';cout<<'\n';tag=next_permutation(a+1,a+1+3);}return 0;
}
其他库函数
memset()
用于设置内存块值的函数,void* memset(void* ptr,int value,size_t num);即指针,值(8位二进制数),重置的大小。通常用来刷“0”或“1”。
int arr[10];
memset(arr,0,sizeof(arr));//将所有数组的所有元素设置为0
swap()
用于交换任意类型的变量
int a=10;
int b=20;
swap(a,b);
reverse()
用于反转容器或数组中元素顺序的函数,只支持双向迭代器的容器。
vector<int> v={1,2,3,4,5};reverse(v.begin(),v.end());for(int num:v)cout<<num<<' ';cout<<'\n';
unique()
用于去除容器中相邻重复元素的函数,unique(first,last)将[first,last)范围内的相邻重复元素去除,并返回一个指向去重后范围的尾后迭代器。
first:指向容器中要去重的第一个元素的下一个位置的迭代器;
last:指向容器中要去重的最后一个元素的下一个位置的迭代器。
vector<int> vec ={1,1,2,2,3,3,3,4,4,5};auto it =unique(vec.begin(),vec.end());vec.erase(it,vec.end());for(int num:vec)cout<<num<<' ';cout<<endl;
int a[]={1,1,2,2,3};int n=unique(a,a+5)-a;for(int i=0;i<5;i++)cout<<a[i]<<' '; //12323for(int i=0;i<n;i++)cout<<a[i]<<' '; //123
int a[]={3,1,2,2,3};int n=unique(a,a+5)-a;for(int i=0;i<n;i++)cout<<a[i]<<' '; //3123sort(a,a+5);for(int i=0;i<n;i++)cout<<a[i]<<' '; //123
1.3 STL
pair
pair的定义和结构
将两个值组合在一起,进行传递、存储和操作
pair<int, double> p1(1,3.14);pair<char, string>p2('a',"hello");cout<<p1.first<<","<<p1.second<<'\n';cout<<p2.first<<","<<p2.second<<'\n';
pair的嵌套
一个pair对象可以作为另一个pair对象的成员,比如三维坐标系的点。
pair<int,int>p1(1,2);pair<int,pair<int,int>>p2(3,make_pair(4,5));pair<pair<int,int>,pair<int,int>>p3(make_pair(6,7),make_pair(8,9));cout<<p1.first<<" "<<p1.second<<endl;cout<<p2.first<<" "<<p2.second.first<<" "<<p2.second.second<<endl;cout<<p3.first.first<<" "<<p3.first.second<<" "<<p3.second.first<<" "<<p3.second.second<<endl;
pair自带排序规则
先对first升序排序,再对second
vector<pair<int,int>>v;v.push_back(make_pair(3,2));v.push_back(make_pair(1,4));v.push_back(make_pair(2,1));//{(3,2),(1,4),(2,1)}sort(v.begin(),v.end());for(const auto& p:v)cout<<p.first<<" "<<p.second<<endl;
//1 4
//2 1
//3 2
代码示例
struct Person{string name;int age;
};int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);vector<Person>people;people.push_back({"Alice",25});people.push_back({"Bob",30});people.push_back({"Charlie",20});vector<pair<Person,int>>scores;scores.push_back({people[0],90});scores.push_back({people[1],95});scores.push_back({people[2],80});for(const auto& pair:scores){cout<<"Name:"<<pair.first.name<<endl;cout<<"Age:"<<pair.first.age<<endl;cout<<"Score:"<<pair.second<<endl;}return 0;
}
vector
vector的定义和特性
动态数组容器
vector的常用函数
元素访问:索引从0开始,最后一个元素的索引是size()-1。(i<size()或者i<=(int)size()-1,因为size返回的是unsigned类型)使用[]运算符或at()函数访问元素。
元素添加和删除:push_back()在末尾添加元素,pop_back()在末尾删除元素(保证vector非空),insert()在指定位置插入元素,erase()在指定位置删除元素。
容器大小管理:size()获得元素数量,empty()检查vector是否为空,resize()调整vector的大小。
迭代器:begin()获取指向第一个元素的迭代器,end()同理。
vector<int>vec={10,20,30};for(auto it =vec.begin();it!=vec.end();it++){cout<<*it<<" ";}
vector排序去重
vector<int>vec={5,3,4,2,6};sort(vec.begin(),vec.end());for(const auto& i:vec){cout<<i<<" ";}
先排序再去重
vector<int>vec={5,3,4,2,2,4,6};sort(vec.begin(),vec.end());auto last=unique(vec.begin(),vec.end());vec.erase(last,vec.end());for(const auto& i:vec){cout<<i<<" ";}
代码示例
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);vector<int>numbers;numbers.push_back(5); numbers.push_back(2);numbers.push_back(8);numbers.push_back(5);numbers.push_back(1);numbers.push_back(2);numbers.push_back(9); numbers.push_back(8);cout<<"原始向量中的元素:";for(const auto& num:numbers){cout<<num<<" ";} cout<<endl;sort(numbers.begin(),numbers.end());cout<<"排序后的向量:";for(const auto&number:numbers){cout<<number<<" ";}cout<<endl;numbers.erase(unique(numbers.begin(),numbers.end()),numbers.end());cout<<"去重后的向量:";for(const auto&number:numbers){cout<<number<<" ";}cout<<endl;numbers.insert(numbers.begin()+2,3);cout<<"插入元素后的向量:";for(const auto&number:numbers){cout<<number<<" ";}cout<<endl;numbers.erase(numbers.begin()+4);cout<<"删除元素后的向量:";for(const auto&number:numbers){cout<<number<<" ";}cout<<endl;if(numbers.empty()){cout<<"向量为空"<<endl;}else{cout<<"向量不为空"<<endl;}cout<<"向量的大小:"<<numbers.size()<<endl;numbers.clear();if(numbers.empty()){cout<<"向量为空"<<endl;}else{cout<<"向量不为空"<<endl;}return 0;
}
list
list的定义和结构
双向链表容器,插入删除访问操作简便,动态大小,不连续存储。
list<int>myList;myList.push_back(1);myList.push_back(2);myList.push_back(3);myList.push_front(0);for(int num:myList){cout<<num<<" ";}cout<<endl;
list的常用函数
代码示例
//创建一个List<int>对象myList list<int>myList;//向myList尾部添加元素 for(int i=1;i<=5;i++){myList.push_back(i);}//从头到尾输出myList中的元素 for(const auto&i:myList)cout<<i<<' ';cout<<'\n';//将myList中的元素反转 reverse(myList.begin(),myList.end());for(const auto&i:myList)cout<<i<<' ';cout<<'\n';//在第一个元素的后一个位置加上元素0myList.insert(++ myList.begin(),0);for(const auto& i:myList)cout<<i<<' ';cout<<'\n'; myList.erase(++ ++myList.begin(),--myList.end());//输出myList的大小cout<<"链表的大小为:"<<myList.size()<<'\n';for(const auto& i:myList)cout<<i<<' ';cout<<'\n';
stack
定义和结构
后进先出(LIFO),stack不能遍历
常用函数
如果将一个数组的元素依次放入栈,再依次取出,可以将数组翻转。
代码示例
stack<int>myStack;myStack.push(10);myStack.push(20);myStack.push(30);myStack.push(40);cout<<"栈顶元素:"<<myStack.top()<<endl;//弹出栈顶元素myStack.pop();cout<<"弹出一个元素之后的栈顶元素:"<<myStack.top()<<endl;if(myStack.empty()){cout<<"栈为空"<<endl;} else{cout<<"栈不为空"<<endl;}//获取栈的大小cout<<"栈的大小:"<<myStack.size()<<endl;
queue
queue队列
先进先出(FIFO)
*priority_queue优先队列
默认情况下,按照元素的值从大到小进行排序,即最大的元素位于队列最前面。
修改比较函数
1.仿函数
struct Compare{bool operator()(int a,int b){//自定义的比较函数,按照逆序排列return a>b; }
};int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);priority_queue<int,vector<int>,Compare>pq;return 0;
}
2.自定义函数
auto compare=[]int(int a,int b){return a>b;
}int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);priority_queue<int,vector<int>,decltype(compare)>pq(compare);return 0;
}
deque双端队列
例题
1.CLZ银行问题 - 蓝桥云课
#include<bits/stdc++.h>
using namespace std;int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int m;cin>>m;queue<string>V,N;while(m--){string op;cin>>op;if(op=="IN"){string name,q;cin>>name>>q;if(q=="V")V.push(name);else N.push(name);}else{string q;cin>>q;if(q=="V")V.pop();else N.pop();}}while(V.size()){cout<<V.front()<<'\n';V.pop();}while(N.size()){cout<<N.front()<<'\n';N.pop();}return 0;
}
1.合并果子 - 蓝桥云课
#include<bits/stdc++.h>
using namespace std;
using ll = long long;int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int n;cin>>n;priority_queue<ll,vector<ll>,greater<ll>>pq;for(int i=1;i<=n;i++){ll x;cin>>x;pq.push(x);}ll ans =0;while(pq.size()>=2){ll x=pq.top();pq.pop();ll y=pq.top();pq.pop();ans += x + y;pq.push(x+y);}cout<<ans<<'\n';return 0;
}
set
*set集合
默认用升序进行排序
修改比较方法
set<int,greater<int>>mySet;mySet.insert(25);mySet.insert(17);mySet.insert(39);mySet.insert(42);for(const auto&i:mySet){cout<<i<<' ';}cout<<'\n';
struct MyCompare{bool operator()(const int & a,const int &b)const{return a>b;}
};int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);set<int,MyCompare>mySet;mySet.insert(25);mySet.insert(17);mySet.insert(39);mySet.insert(42);for(const auto& i:mySet){cout<<i<<' ';}cout<<endl;return 0;
}
*multset多重集合
允许存储重复的元素
unordered_set无序集合
没有特定顺序
代码示例
set<int>mySet;mySet.insert(5);mySet.insert(2);mySet.insert(8);mySet.insert(2);//重复元素 for(const auto& i:mySet){cout<<i<<' ';}cout<<endl;//查找元素int searchValue=5;auto it =mySet.find(searchValue);if(it!=mySet.end()){cout<<"找到该元素"<<endl; }else{cout<<"未找到该元素"<<endl;} //移除元素int removeValue=2;mySet.erase(removeValue);//再次遍历集合for(const auto& i:mySet){cout<<i<<' ';}cout<<endl;//清空集合mySet.clear(); if(mySet.empty()){cout<<"集合为空"<<endl;}else{cout<<"集合不为空"<<endl;}
multiset<int>myMultiset;myMultiset.insert(5);myMultiset.insert(2);myMultiset.insert(8);myMultiset.insert(2);//重复元素 for(const auto& i:myMultiset){cout<<i<<' ';}cout<<endl;//查找元素int searchValue=5;auto it =myMultiset.equal_range(searchValue);if(it.first!=it.second){cout<<"找到该元素"<<endl; }else{cout<<"未找到该元素"<<endl;} //移除元素int removeValue=2;
// myMultiset.erase(removeValue);//将两个2都移除 myMultiset.erase(myMultiset.find(2));//只移除一个2 //再次遍历集合for(const auto& i:myMultiset){cout<<i<<' ';}cout<<endl;//清空集合myMultiset.clear(); if(myMultiset.empty()){cout<<"集合为空"<<endl;}else{cout<<"集合不为空"<<endl;}
map
*map
关联容器,用于存储一组键值对,其中每个键都是唯一的。
multimap(几乎用不到)
允许存储多个具有相同键的键值对
unordered_map(很少用到)
无序
代码示例
int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);//创建并初始化mapmap<int,string>myMap={{1,"Apple"},{2,"Banana"},{3,"Orange"}};//插入元素myMap.insert(make_pair(4,"Grapes"));//查找和访问元素cout<<myMap[2]<<endl;//遍历并打印map中的元素for(const auto&pair:myMap){cout<<"Key:"<<pair.first<<",Value:"<<pair.second<<endl;} //删除元素myMap.erase(3);//判断元素是否存在if(myMap.count(3)==0){cout<<"Key 3 not found."<<endl;} //清空mapmyMap.clear();//判断map是否为空if(myMap.empty()){cout<<"Map is empty."<<endl;} return 0;
}
总结
3226 宝藏排序II
1.宝藏排序Ⅱ - 蓝桥云课
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+9;
int a[N];int main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);int n;cin>>n;for(int i=1;i<=n;i++)cin>>a[i];sort(a+1,a+1+n);for(int i=1;i<=n;i++)cout<<a[i]<<' ';cout<<'\n';return 0;
}
1624 小蓝吃糖果
1.小蓝吃糖果 - 蓝桥云课
优先队列或者用max变量求最大值
#include <bits/stdc++.h>
using namespace std;
int main()
{int n; cin>>n;priority_queue<int>pq;long long sum=0;for(int i=1;i<=n;i++){int x;cin>>x;pq.push(x);sum+=x;}long long mx=pq.top();if(sum-mx>=mx-1)cout<<"Yes"<<'\n';else cout<<"No"<<'\n';return 0;
}
2490 小蓝的括号串1
1.小蓝的括号串1 - 蓝桥云课
#include <bits/stdc++.h>
using namespace std;const int N=105;
stack<char>stk;
char s[N];int main()
{int n;cin>>n;cin>>s+1;bool ans =true;for(int i=1;i<=n;i++){if(s[i]=='(')stk.push('(');else{if(stk.size()&&stk.top()=='(')stk.pop();else ans=false;}}if(stk.size())ans=false;cout<<(ans?"Yes":"No")<<'\n';return 0;
}
1531 快递分拣
#include <bits/stdc++.h>
using namespace std;
map<string,vector<string>>mp;
vector<string>citys;
int main()
{int n;cin>>n;for(int i=1;i<=n;i++){string a,b;cin>>a>>b;if(!mp.count(b))citys.push_back(b);mp[b].push_back(a);}for(const auto&city:citys){cout<<city<<' '<<mp[city].size()<<'\n';for(const auto & i:mp[city]){cout<<i<<'\n';}}return 0;
}