STL
STL?
標準樣板函式庫
Standard Template Library
裡面有很多容器、函式
很多好用的工具
演算法的基礎
請務必學會並弄熟
INDEX
- vector
- pair
- stack
- queue
- deque
- set/multiset
- map
- priority_queue
- bitset
Vector
Vector
常用功能:
push_back
pop_back
clear
size
empty
宣告
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int>v;
//宣告一個陣列
vector<char>a(10);
//大小為10
vector<int>b={1,3,5};
//直接指定大小&賦值
vector<int>(12,0);
//大小為4且都放0
}vector<資料型態> 名稱;
加入/移除元素
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int>v;
v.emplace_back(1);
//加入元素 較快
v.push_back(2);
//加入元素 較慢
v.pop_back();
//移除尾端元素
}push_back(值);
emplace_back(值);
pop_back();
取值
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int>v;
v.emplace_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
cout<<v[2];
}基本上陣列可以做到的
vector也都可以
取頭尾
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int>v;
v.emplace_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
cout<<v.front()<<v.back()<<v[2];
}front():第一項
back():最末項
基本上陣列可以做到的
vector也都可以
大小
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> v;
cout<<"初始:size="<<v.size()<<" capacity="<<v.capacity()<<'\n';
for (int i = 1; i <= 10; i++) {
v.push_back(i);
cout<<"插入"<<i<<"->size="<<v.size()<<" capacity="<<v.capacity()<<'\n';
}
}size():取得vector的長度
capacity():陣列加上預留的格子
empty():判斷是否為空 回傳布林值
Vector

size():vector長度
capacity():預留的記憶體空間(通常用倍增)
迭代器 iterator
vector是一排的盒子
iterater像指針 指向陣列的位置(不是值)
宣告方法:
vector<int>::iterator it;變數it 是指向vector<int>的迭代器型別
begin():vector第一格的位置
end():vector最後一格"再下一格"的位置
移動迭代器:
it++:移到下一格
it--:移到上一格
遍歷
1.用for
跑過整個陣列
vector<int>v={1,2,3,4,5};
for(int i=0;i<5;i++){
cout<<v[i]<<' ';
}跟陣列一樣
遍歷
2.用剛剛學過的迭代器
vector<int>v={1,2,3,4,5};
for(vector<int>::iterator it=v.begin();it!=v.end();it++){
cout<<*it<<' ';//'*'用來取值
}這樣也太長了吧
在C++11後 提供auto可以自動判斷型別
vector<int>v={1,2,3,4,5};
for(auto it=v.begin();it!=v.end();it++){
cout<<*it<<' ';
}遍歷
3.range-based for
vector<int>v={1,2,3,4,5};
for(int i:v){
cout<<i<<' ';
}複製每個元素到i裡面
但是改動i不會影響v裡面的東西
vector<int>v={1,2,3,4,5};
for(int i:v){
cout<<i<<' ';
i+=10;
}
cout<<'\n';
for(int x:v){
cout<<x<<' ';
}參考(reference)
變數的別名
所以改動的時候也會改動原變數
在變數前面加上'&'
vector<int>v={1,2,3,4,5};
for(int &i:v){
cout<<i<<' ';
i+=10;//用了參照 v裡面的值也會改
}
cout<<'\n';
for(int x:v){
cout<<x<<' ';
}一些特殊操作
常用:
sort():由小到大排
reverse():反轉
swap():兩元素調換
fill():填滿陣列格子
resize():重新定義大小
vector<int>v={1,2,3,4,5};
sort(v.begin(),v.end());
reverse(v.begin(),v.end());
swap(v[1],v[3]);
fill(v.begin(),v.end(),0);
v.resize(10);自己操作看看
未來的圖論會用到
也可以直接當成陣列使用
是個極為方便的工具
o076
#include<bits/stdc++.h>
using namespace std;
vector<int>v;
int main(){
int n;cin>>n;
for(int i=0;i<n;i++){
int a;cin>>a;
v.push_back(a);
}
int x=v[0],tmp=1,ans=1;
for(int i=1;i<n;i++){
if(v[i]<v[i-1])tmp++;
else tmp=1;
ans=max(ans,tmp);
}
cout<<ans<<'\n';
}
toj 575
#include<bits/stdc++.h>
#define maxn 1000005
using namespace std;
vector<int>g[maxn];
int main(){
int n,k;cin>>n>>k;
for(int i=0;i<k;i++){
int a,b;cin>>a>>b;
g[a].push_back(b);
g[b].push_back(a);
}
for(int i=1;i<=n;i++){
sort(g[i].begin(),g[i].end());
for(auto x:g[i]){
cout<<x<<' ';
}
cout<<'\n';
}
}Pair
Pair
把兩組資料綁在一起
看成一種新的型態
pair<int,int>p宣告方式跟vector很像
pair<資料型態,資料型態>名稱;
取值
first:第一項
second:第二項
#include<bits/stdc++.h>
using namespace std;
int main(){
pair<int,int>p;
p.first=3;//將第一項設成3
p.second=5;
cout<<p.first<<' '<<p.second<<'\n';
}宣告方式跟vector很像
pair<資料型態,資料型態>名稱;
不用加()
vector+pair
pair裡面可以裝整數
當然也可以裝任何資料型態
#include<bits/stdc++.h>
using namespace std;
int main(){
pair<int,int>p;
pair<int,pair<int,int>>p1;
pair<int,char>p2;
pair<vector<int>,pair<int,int>>p3;
}vector+pair
vector也不例外
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<int>v;
vector<pair<int,int>>v1;
vector<vector<int>>v2;
}注意事項
在傳入和輸出的時候有些要注意
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<pair<int,int>>v;
v.push_back(make_pair(3,5));
v.push_back({3,5});
v.emplace_back(3,5);
}vector要放pair要加make_pair(a,b)或{a,b}
emplace_back(a,b)直接放
pair不能直接輸出 要分開用first second取
大小比較
在用sort()函式比較pair的大小時
#include<bits/stdc++.h>
using namespace std;
int main(){
vector<pair<int,int>>v;
v.push_back(make_pair(3,5));
v.push_back({5,5});
v.emplace_back(5,7);
sort(v.begin(),v.end());
}會先比較first 再比較second
練習
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
vector<pair<int,int>>v;
for(int i=0;i<n;i++){
int x,y;
cin>>x>>y;
v.push_back({x,y});
}
sort(v.begin(),v.end());
for(auto i:v)cout<<i.first<<' '<<i.second<<'\n';
}a130
#include<bits/stdc++.h>
using namespace std;
int main(){
int t;cin>>t;
int cnt=1;
while(t--){
int mx=0;
vector<pair<string,int>>v;
for(int i=0;i<10;i++){
string c;
int a;
cin>>c>>a;
v.push_back({c,a});
mx=max(mx,a);
}
cout<<"Case #"<<cnt<<":\n";
for(int i=0;i<10;i++){
if(mx==v[i].second)cout<<v[i].first<<'\n';
}
cnt++;
}
}
Stack
Stack
後進先出(LIFO)
有點像堆疊 書堆的概念
或是一個乒乓球桶的感覺
常用功能:
push()
pop()
top()

宣告
stack<資料型態>名稱;
stack<int>st;
stack<char>stk;無法預設大小
可以用size()來看有多長
empty()看是否為空
推入移除元素
push():從尾端推入元素
pop():從尾端移除元素
在pop的時候
如果不確定大小時
記得要檢查是否為空
否則會出錯(RE)
stack<int>st;
st.push(1);
st.push(2);
st.push(3);
st.pop();
if(!st.empty())st.pop();
取值
無法用[]取值
top():
拿最上面的那個
只能拿最上面那一個
若stack為空也會RE
stack<int>st;
st.push(1);
st.push(2);
st.push(3);
st.pop();
cout<<st.top()<<' ';
題目
i213
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
stack<int>st;
for(int i=0;i<n;i++){
int a;cin>>a;
if(a==1){
int b;cin>>b;
st.push(b);
}
else if(a==2){
if(st.empty())cout<<-1;
else cout<<st.top();
cout<<'\n';
}
else{
if(!st.empty())st.pop();
}
}
}
f345
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
stack<int>st;
for(int i=0;i<n;i++){
int a;cin>>a;
st.push(a);
}
while(!st.empty()){
cout<<st.top()<<' ';
st.pop();
}
}
Queue
Queue
先進先出(FIFO)
排隊的概念
跟stack有相反的感覺
常用功能:
push()
pop()
front()
宣告
queue<資料型態>名稱;
queue<int>q;
queue<char>qq;和stack基本一樣
無法預設大小
size()看有多長
empty()檢查是否為空
推入移除元素
push():從尾端推入元素
pop():從最前端移除元素
queue<int>q;
q.push(1);
q.push(2);
q.push(3);
q.pop();
if(!q.empty())q.pop();pop的時候一樣要注意是否為空
取值
front():取最前面元素
queue<int>q;
q.push(1);
q.push(2);
q.push(3);
q.pop();
cout<<q.front<<' ';
if(!q.empty())q.pop();
pop的時候一樣要注意是否為空
題目
e447
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;cin>>n;
queue<int>q;
for(int i=0;i<n;i++){
int a;cin>>a;
if(a==1){
int b;cin>>b;
q.push(b);
}
else if(a==2){
if(q.empty())cout<<-1;
else cout<<q.front();
cout<<'\n';
}
else{
if(!q.empty())q.pop();
}
}
}
Deque
Deque
怎麼唸?
dq?
deck
雙端佇列
(double-ended queue)
stack+queue
宣告
方法跟前面兩個基本差不多
直接放code
#include<bits/stdc++.h>
using namespace std;
int main(){
deque<int>dq;
deque<char>dq1;
}推入移除元素
雙向=可從頭尾加入移除元素
push_back(),pop_back():從後端增減元素
push_front(),pop_front:從前端加減元素
#include<bits/stdc++.h>
using namespace std;
int main(){
deque<int>dq;
dq.push_front(1);
dq.push_back(2);
dq.push_back(3);
dq.pop_back();
dq.pop_front();
}取值
front():最前端元素
back():最後端元素
#include<bits/stdc++.h>
using namespace std;
int main(){
deque<int>dq;
dq.push_front(1);
dq.push_back(2);
dq.push_back(3);
cout<<dq.front()<<dq.back();
}大小
empty():判斷是否為空
size():回傳大小
#include<bits/stdc++.h>
using namespace std;
int main(){
deque<int>dq;
dq.push_front(1);
dq.push_back(2);
dq.push_back(3);
if(dq.empty())cout<<"empty!\n";
cout<<dq.size();
}缺點
各個操作都比vector慢3倍
沒事不要用到它
沒事不要用到它
沒事不要用到它
開stack跟queue的時候其實都是在開一個deque
所以速度上stack=queue=deque
題目
如果要練習的話
就用deque把前面的題目寫一次
Set/Multiset
Set
集合
裡面元素都是唯一(不重複)
且都排序好的
實作方式 紅黑樹
很難很複雜(我不會)
宣告
set<int>s;
set<char>st;就像一個黑盒子
1.可以放東西進去
2.拿東西出來
3.詢問一個東西是否在裡面
放入/移除東西
set<int>st;
st.insert(1);
st.insert(2);
st.insert(3);
st.erase(1);
insert():放入東西
erase():移除東西
把1移除
裡面剩下2 3
查詢
set<int>st;
st.insert(1);
st.insert(2);
st.insert(3);
if(st.find(2)!=st.end())cout<<"Yes\n";
if(st.count(2))cout<<"Yes\n";
if(st.empty())cout<<"empty";
find():如果找到 回傳記憶體位置
(如果沒找到 回傳end())
count():裡面有幾個
empty():是否為空
查詢
set<int>st;
st.insert(1);
st.insert(2);
st.insert(3);
auto it=st.find(2);
//auto=set<int>::iterater
if(it!=st.end())cout<<*it;
find()回傳的是記憶體位置
輸出位置的值的話加個*
不知道各位有沒有忘記它
迭代器
set<int>st;
st.insert(1);
st.insert(2);
st.insert(3);
auto it=st.begin(2);
//auto=set<int>::iterater
cout<<*it<<'\n';
cout<<*next(it)<<'\n';
cout<<*prev(it)<<'\n';
begin(),end()
prev():此記憶體位置的前一項
next():此記憶體位置的前一項
可以不用修改it的值
用法
set<int>st;
st.insert(1);
st.insert(2);
st.insert(3);
auto it=st.begin();
//auto=set<int>::iterater
cout<<*next(it)<<'\n';
cout<<*(++it)<<'\n';
如何用set輸出第2小的數字?
set裡面的元素是有序的
第二大=第二個元素
可以思考一下兩種輸出有什麼差別
遍歷
set<int>st;
st.insert(1);
st.insert(2);
st.insert(3);
for(int i:st)cout<<i<<'\n';
for(auto iter=st.begin();iter!=s.end();iter++){
cout<<*iter<<'\n';
}
跟vector差不多
一般用上面那種
搜尋
set<int>st;
st.insert(1);
st.insert(2);
st.insert(3);
cout<<*st.upper_bound(2);
set有upper_bound()函式
.upper_bound(k)尋找第一個大於k的位置
注意 是位置 值的話*
(為甚麼說"也有" 因為我還沒講)
不滿足?
set一種元素只能存一個
不夠 要更多?
STL有個東西叫做Multiset
Multiset
可以同時存在多個相同元素
與set語法大致相同
1.count():可回傳元素數量
2.erase(n):刪除所有為n的元素
只刪除一個:s.erase(s.find(10))
multiset<int>st;
st.insert(1);
st.insert(1);
st.insert(2);
st.insert(3);
cout<<st.count(1)<<'\n';
太多了?
只要知道元素是否在裡面
不用排序?
STL 還有個東西是unordered_set !!!
unordered_set
功能如其名
底層用hash實作
失去upper_bound功能
整體比set快
有時候可以拿來優化
(還有unordered_multiset)
總結
目前用法最特殊的
功能也一堆
不過多寫點題目
每次反覆使用
就可以輕鬆拿捏
Set挺重要的
題目
b130
想法:
輸出大小
按照順序輸出
相同的去掉
用set
#include<bits/stdc++.h>
using namespace std;
int main(){
set<int>st;
int n,a;
cin>>n;
for(int i=0;i<n;i++){
cin>>a;
st.insert(a);
}
cout<<st.size()<<'\n';
for(auto x:st){
cout<<x<<' ';
}
}cses distinct number
想法:
不同值的數量
有點像...
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
set<int>s;
for(int i=0;i<n;i++){
int a;
cin>>a;
s.insert(a);
}
cout<<s.size();
}
沒錯 set的大小
d123
想法:
用set來檢查是否出現過
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,c=1;
while(cin>>n){
int arr[1005];
set<int>st;
for(int i=0;i<n;i++){
cin>>arr[i];
}
bool flag=1;
for(int i=0;i<n-1;i++){
for(int j=i;j<n;j++){
int tmp=arr[i]+arr[j];
if(st.count(tmp)){
flag=0;
break;
}
st.insert(tmp);
}
if(!flag)break;
}
if(flag)cout<<"Case #"<<c<<": It is a B2-Sequence.\n";
else cout<<"Case #"<<c<<": It is not a B2-Sequence.\n";
c++;
}
}
count()>0代表出現過
可以用unordered_set
m932
想法:
陣列操作(複雜)
用set來計算種類數
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
set<char>st;
int dx[6]={-1,0,1,1,0,-1};
int dy[6]={0,1,1,0,-1,-1};
int main(){
string s="";
cin>>n>>m>>k;
char v[25][25];
for(int i=0;i<n;i++){
string b;
cin>>b;
for(int j=0;j<m;j++){
v[i][j]=b[j];
}
}
int x=n-1,y=0;
for(int i=0;i<k;i++){
int a,tx,ty;
cin>>a;
tx=x+dx[a];
ty=y+dy[a];
if((tx<n&&tx>=0)&&(ty<m&&ty>=0)){
x+=tx-x;
y+=ty-y;
}
st.insert(v[x][y]);
s+=v[x][y];
}
cout<<s<<'\n';
cout<<st.size();
}count()>0代表出現過
可以用unordered_set
m932
想法:
陣列操作(複雜)
用set來計算種類數
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
set<char>st;
int dx[6]={-1,0,1,1,0,-1};
int dy[6]={0,1,1,0,-1,-1};
int main(){
string s="";
cin>>n>>m>>k;
char v[25][25];
for(int i=0;i<n;i++){
string b;
cin>>b;
for(int j=0;j<m;j++){
v[i][j]=b[j];
}
}
int x=n-1,y=0;
for(int i=0;i<k;i++){
int a,tx,ty;
cin>>a;
tx=x+dx[a];
ty=y+dy[a];
if((tx<n&&tx>=0)&&(ty<m&&ty>=0)){
x+=tx-x;
y+=ty-y;
}
st.insert(v[x][y]);
s+=v[x][y];
}
cout<<s<<'\n';
cout<<st.size();
}count()>0代表出現過
可以用unordered_set
Map
Map
前面教過陣列取值
int arr[105];
arr[5]=3;
cout<<arr[5]<<'\n';陣列名稱[索引值]
索引5 對應到的值是3
那今天如果索引值不是整數?
只有辦法從0到陣列大小-1嗎?
Map
那肯定是可以的
map就是在做這件事
map<int,int>mp;//宣告
map<string,int>mp1;
map<string,string>mp2;map能夠將一個鍵(key)
對應到一個值(value)
可以把它當查資料
輸入書名 告訴你作者是誰
新增與指派
map<int,int>mp;//宣告
map<string,int>mp1;
mp[5]=3;
mp[3]++;
mp1["abc"]=100;
mp.erase(5);//刪除如果key存在 修改它的值
否則新增一個key
一個新的key預設值
整數是0
字串是""
查詢
map<int,int>mp;//宣告
mp[5]=3;
cout<<mp[5]<<'\n';
cout<<mp[0]<<'\n';如果key存在 輸出它的值
否則新增一個value是預設值的key
所以mp[0]是0
遍歷
map<int,int>mp;//宣告
mp[5]=3;
mp[0]=10;
for(pair<int,int> i:mp){
cout<<i.first<<' '<<i.second<<'\n';
}會按照key的值由小到大排
型態是pair
first是key
second是value
pair太長了 寫auto比較簡略
Map
底層結構是紅黑樹
跟set一樣
插入、刪除、查詢的時間複雜度
都是O(log n) n是map大小
如果key不想要排序?
unordered_map
實作方式改為hash
失去順序
插入、查詢、刪除的複雜度變成O(1)
題目
a135
#include<bits/stdc++.h>
using namespace std;
int main(){
unordered_map<string,string>mp;
mp["HELLO"]="ENGLISH";
mp["HOLA"]="SPANISH";
mp["HALLO"]="GERMAN";
mp["BONJOUR"]="FRENCH";
mp["CIAO"]="ITALIAN";
mp["ZDRAVSTVUJTE"]="RUSSIAN";
int t=1;
string s;
while(cin>>s && s!="#"){
cout<<"Case "<<t<<": ";
if(mp[s]!="")cout<<mp[s]<<'\n';
else cout<<"UNKNOWN\n";
t++;
}
}
基本的查詢
e641
#include<bits/stdc++.h>
using namespace std;
int main(){
string s,a;
map<string,int>m{
{"B",1},{"F",1},{"P",1},{"V",1},
{"C",2},{"G",2},{"J",2},{"K",2},{"Q",2},{"S",2},{"X",2},{"Z",2},
{"D",3},{"T",3},
{"L",4},
{"M",5},{"N",5},
{"R",6}
};
int x=0;
while(cin>>s){
for(int i=0;i<s.size();i++){
a=s[i];
if(m[a]==0){
x=0;
continue;
}
else if(m[a]==x)continue;
else x=m[a];
cout<<x;
}
cout<<'\n';
}
}另一種建立key value的方式
其他都基本操作
d518
#include<bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0);
int n;
while(cin>>n){
string s;
int x=1;
map<string,int>m;
for(int i=1;i<=n;i++){
cin>>s;
if(m[s]!=0){
cout<<"Old! "<<m[s]<<'\n';
}
else{
m[s]=x;
x++;
cout<<"New! "<<m[s]<<'\n';
}
}
}
}利用map記第幾個
Priority_Queue
priority_queue
功能:將數字丟進去,由大排到小
可以查詢最大值
可以刪除最大值
優先隊列
宣告
priority_queue<int>pq;如果想要由小排到大
priority_queue<int,vector<int>,greater<int>>pq;加入/移除
priority_queue<int>pq;
pq.push(3);
pq.push(5);
pq.push(4);
pq.push(1);
pq.pop();
pq.push(2)push():加入一個數字
pop():刪除最大值
查詢
priority_queue<int>pq;
pq.push(3);
pq.push(5);
pq.push(4);
cout<<pq.top();top():查詢最大值
常用
priority_queue<int>pq;
pq.push(3);
pq.push(5);
pq.push(4);
cout<<pq.size();
if(!pq.empty())cout<<pq.top();empty():回傳是否為空
size():回傳大小
其他
實作是用heap
資芽會教 去報名
複雜度雖然跟set一樣(O(log(n))
但常數比較小
有很多greedy的題目會用到
題目
d221
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main(){
int n,a;
priority_queue<ll,vector<ll>,greater<ll>>pq;
while(cin>>n &&n!=0){
ll ans=0;
for(int i=0;i<n;i++){
cin>>a;
pq.push(a);
}
while(pq.size()>1){
int a,b,cost;
a=pq.top();
pq.pop();
b=pq.top();
pq.pop();
cost=a+b;
ans+=cost;
pq.push(cost);
}
cout<<ans<<'\n';
pq.pop();
}
}Bitset
布林陣列
bool arr[10005];裡面都存布林值(0,1)
bitset
特別優化過的布林陣列
空間跟時間都有優化
尤其是時間
宣告
<>裡面放的是大小
bitset<100005>bs;開一個大小為100005的陣列
語法
bitset<100005>bs;
b[3]=1;//第四項為true
b[2]=1;
cout<<b[1];和布林陣列一樣
特殊語法
bitset<100005>bs;
b[3]=1;//第四項為true
b[2]=1;
cout<<b.count();
b.reset();
b.set();count():回傳裡面1的數量
set():全部設成1
reset():全部設成0
快?
bitset可以進行位元運算
速度極快
大概是正常的1/32倍
所以有些題目可以用bitset優化
但那些題目挺難
之後有機會可以分享
遇到布林陣列的題目或位元運算操作的題目可以用bitset練習看看
常用工具/函式
min/max
用來求最小最大值
int a=10,b=5,c=11;
cout<<min(a,b);
cout<<max(b,c);
cout<<max({a,b,c});
//3個數字加大括號要注意不同型別不能比較
long long跟int不能放一起
int a=10;
long long b=5;
cout<<min((long long)a,b);
//強制轉型
abs
絕對值
int a=10,b=-10;
cout<<abs(a)<<'\n';
cout<<abs(b)<<'\n';回傳的型態跟傳入值一樣
swap
交換兩數
int a=10,b=130;
cout<<a<<' '<<b<<'\n';
swap(a,b);
cout<<a<<' '<<b<<'\n';之前排序的code也有
可以交換陣列的兩項
sqrt
開根號
int a=100,b=15;
cout<<sqrt(a)<<'\n';
cout<<sqrt(b)<<'\n';回傳型態跟輸入值相同
複雜度:
pow
pow(a,b)回傳a的b次方
int a=2,b=15;
cout<<pow(a,b)<<'\n';複雜度不一定 雖然底層是用快速冪
但聽說因為很慢 被叫慢速冪
用浮點數運算
會有誤差 別用
__gcd
__gcd(a,b)回傳a,b的最大公因數
int a=243,b=15;
cout<<__gcd(a,b)<<'\n';複雜度:
__lg
__lg(a)回傳a以2為底取對數值
int a=1024;
cout<<__lg(a)<<'\n';複雜度:
傳入必須是整數
回傳會取整
log
回傳以e為底的對數值
int a=50;
cout<<log(a)<<'\n';複雜度:
浮點數運算
sort
sort(a,b)
將a位置(包含)到b位置(不包含)元素由小到大排
int arr[4]={3,2,1,4};
sort(arr,arr+4);
for(int i=0;i<4;i++){
cout<<arr[i]<<' ';
}複雜度:
開始 結束
sort
隱藏參數?
sort(a,b,cmp)
cmp如果回傳false則交換
bool cmp(int a,int b){
return a>b;
}從大排到小
也有其他種 比如二維點或其他種structure
greater<int>()
reverse
reverse(a,b)
將a位置(包含)到b位置(不包含)元素反轉
int arr[4]={3,2,1,4};
reverse(arr+1,arr+4);
for(int i=0;i<4;i++){
cout<<arr[i]<<' ';
//3 4 1 2
}字串蠻常用到的
min(/max)_element
min/max_element(a,b)
回傳a位置(包含)到b位置(不包含)最小/大值的指標
int arr[4]={3,2,1,4};
cout<<*min_element(arr,arr+4)<<'\n';
cout<<min_element(arr,arr+4)-arr;找到的位置-第一項的位置=它的index
fill
fill(a,b,c)
回傳a位置(包含)到b位置(不包含)的值變成c
int arr[4]={3,2,1,4};
fill(arr,arr+3,6767);
for(int i=0;i<4;i++){
cout<<arr[i]<<' ';
}可用於初始化陣列
lower_bound
lower_bound(a,b,c)
回傳a位置(包含)到b位置(不包含)第一個>=c的位置
int arr[4]={-10,2,12,48};
sort(arr,arr+4);
cout<<*lower_bound(arr,arr+4,3)回傳b的話 代表沒找到
要再由小到大排的陣列才可使用
upper_bound
upper_bound(a,b,c)
回傳a位置(包含)到b位置(不包含)第一個>c的位置
int arr[4]={-10,2,12,48};
sort(arr,arr+4);
cout<<*upper_bound(arr,arr+4,3)回傳b的話 代表沒找到
要再由小到大排的陣列才可使用
IO優化
IO優化
有時候題目一直TLE
卻想不到怎麼優化
輸入量又很大
怎麼辦
IO優化!
IO優化
ios::sync_with_stdio(0),cin.tie(0);
可以當成模板打
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0);
}放在main函式裡面
可以加速輸入輸出
IO優化
ios::sync_with_stdio(0),cin.tie(0);
可以當成模板打
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(0),cin.tie(0);
}放在main函式裡面
可以加速輸入輸出
但是打上去後cin就不能和scanf混用
IO優化
sync_with_stdio(0)
如何優化的?
會關閉cin cout scanf printf 的同步
減少性能損失
所以打了之後不能混用
IO優化
cin.tie(0)
如何優化的?
當電腦cin的時候 會刷新緩衝區
讓輸入前將輸出完成
但就會耗費很多時間
cin.tie(0)
關閉了此動作
所以可以加速
IO優化
cin.tie(0)
如何優化的?
當電腦cin的時候 會刷新緩衝區
讓輸入前將輸出完成
但就會耗費很多時間
cin.tie(0)
關閉了此動作
所以可以加速
指標
指標
類似一個變數的概念
但它存的是16進位的記憶體位置
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[10] = {2,4,3,5,12,5,23,6,3,6};
cout<<a<<endl;
}去跑跑看
會回傳a[0]的記憶體位置
指標
如果知道一個指標
要怎麼知道真正的值
*
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[10] = {2,4,3,5,12,5,23,6,3,6};
cout<<*a<<endl;
}指標
那如果知道一個值
要怎麼知道它的指標
&
#include<bits/stdc++.h>
using namespace std;
int main(){
int a = 5;
int *ptr = &a;
cout<<ptr<<endl;
}指標
C++的*有兩種功能
(1)取出指標的值
(2)指標變數
當這個變數要存指標時 就需要加*
#include<bits/stdc++.h>
using namespace std;
int main(){
int a = 5;
int *ptr = &a;
cout<<ptr<<endl;
}指標
#include<bits/stdc++.h>
using namespace std;
int main(){
int a = 5;
int *ptr = &a;
cout<<a<<endl;
*ptr = 10;
cout<<a<<endl;
}既然ptr存的是a的記憶體位置
那是不是就可以直接改a的值
指標
#include<bits/stdc++.h>
using namespace std;
int main(){
int a[10] = {23,4,3,5,12,5,23,6,3,6};
cout<<*(a+4)<<endl;
cout<<*(a+7)<<endl;
}好想有點似曾相識?
指標
int main(){
int a[10] = {23,4,3,5,12,5,23,6,3,6};
cout<<*(a+4)<<endl;
cout<<*(a+7)<<endl;
cout<<a[4]<<endl;
cout<<a[7]<<endl;
}沒錯 跟[]是一模一樣的東西
指標
小結:
非常抽象
是個很厲害很好用的工具
linked list,動態開點線段樹...
還有一堆極抽象的東西
在高中競程用的比較少
我有很熟
STL
By wuchanghualeo
STL
- 202