STL
STL有很多東西,忘了怎麼辦??
STL有很多東西,忘了怎麼辦??
忘了就查,查幾次就會記得了 !!
cppreference
container
Vector
功能比較多
可以自動改大小的陣列
front()
back()
第一個元素
最後一個元素
begin() 第一個元素的指標
end() 結束的指標(最後一個元素的下一個位置)
rbegin() 最後一個元素的指標
rend() 開始的指標-1(第一個元素的上一個位置)
clear()
insert() 一般不會用(很慢)
push_back()
pop_back()
resize() (長度,數值)
empty()
size()
vector會什麼可以一直push_back()
但不用預先訂長度
試試模板
請寫一個程式,可以有幾種輸入
1: push X 推入 X
2 : pop 移除最後一個元素
3 : clear 清除vector
4 : size 印出目前長度
每次操作後印出整個陣列
First in Last out
推疊
推疊
能從頂端拿東西 / 放東西

| 名稱 | 功能 | 時間 |
|---|---|---|
| empty() | 回傳是否為空 | O(1) |
| size() | 大小 | O(1) |
| push() |
推入一元素 | O(1) |
| pop() | 刪除一元素(頂端) | O(1) |
| swap() | 交換兩stack | O(1) |
| top() | 回傳頂端元素 | O(1) |
扣
#include<bits/stdc++.h>
using namespace std;
main(){
stack<int> st;
st.push(3);
st.push(4)
st.push(6);
cout<<st.top()<<endl;
st.pop();
cout<<st.top()<<endl;
st.pop();
if(st.empty()) cout<<"empty!!"<<endl;
else cout<<"not empty!!"<<endl;
}
AC code
#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
stack<int> A,st;
int n,T,q[maxn],inst[maxn];
bool flag;
int main(){
cin>>T;
while(T--){
flag = true;
while(!A.empty()) A.pop();
while(!st.empty()) st.pop();
cin>>n;
for(int i=1;i<=n;++i) inst[i]=0;
for(int i=n;i>=1;--i) A.push(i);
for(int i=0;i<n;++i) cin>>q[i];
for(int i=0;i<n;++i){
if(!inst[q[i]]){
while(A.top()!=q[i]){
st.push(A.top());
inst[A.top()]=1;
A.pop();
}
A.pop();
}else if(st.empty()||st.top() != q[i]){
flag = false;
break;
}
else {
inst[st.top()] = 0;
st.pop();
}
}
if(flag) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}Queue
First in First out

像是一條隊伍,前面的人可以出去,人可以從後面進入隊伍
| 名稱 | 功能 | 時間 |
|---|---|---|
| empty() | 回傳是否為空 | O(1) |
| size() | 大小 | O(1) |
| push() | 推入一元素 | O(1) |
| pop() | 刪除一元素(頂端) | O(1) |
| front() | 回傳開始端的元素 | O(1) |
| back() | 回傳尾端元素 | O(1) |
扣
#include<bits/stdc++.h>
using namespace std;
main(){
queue<int> Q;
Q.push(34);
Q.push(3);
Q.push(65);
Q.push(8);
cout<<Q.front()<<endl;
cout<<Q.back()<<endl;
Q.pop();
cout<<Q.front()<<endl;
cout<<Q.back()<<endl;
if(Q.empty()) cout<<"empty!!"<<endl;
else cout<<"not empty!!"<<endl;
cout<<Q.size()<<endl;
}
經常用於之後會教的BFS、單調隊列
stack + queue
頭尾都可以拿取元素或推入元素
| 名稱 | 功能 | 時間 |
|---|---|---|
| empty() | 回傳是否為空 | O(1) |
| size() | 大小 | O(1) |
| front() | 回傳開始端的元素 | O(1) |
| back() | 回傳尾端元素 | O(1) |
| push_back() | 從後端推入元素 | O(1) |
| push_front() | 從前端推入元素 | O(1) |
| pop_back() | 從後端刪除元素 | O(1) |
| pop_front() | 從前端刪除元素 | O(1) |
扣
#include<bits/stdc++.h>
using namespace std;
main(){
deque<int> dq;
dq.push_front(4);
dq.push_front(4325);
dq.push_back(32);
dq.push_front(1);
dq.push_back(4);
dq.push_back(56);
dq.push_front(6);
cout<<dq.front()<<endl;
cout<<dq.back()<<endl;
dq.pop_back();
dq.pop_front();
dq.pop_back();
cout<<dq.size()<<endl;
cout<<dq.front()<<endl;
cout<<dq.back()<<endl;
}
Set & Multiset
set -> 集合
想像一個黑盒子,可以有種操作
1:放入一個東西
2:拿出一個東西
3:詢問一個東西是否在裡面
BUT!!
同一個東西只能放一個
BUT!!
同一個東西只能放一個
Multiset想放幾個就放幾個
| 名稱 | 功能 | 時間 |
|---|---|---|
| empty() | 回傳是否為空 | O(1) |
| size() | 大小 | O(1) |
| insert() | 插入元素 | O(logn) |
| erase() | 刪除元素 | O(logn) |
| find() | 是否找到元素 | O(logn) |
| count() | 是否找到元素 | O(logn) |
| lower_bound() | 第一個大於等於 | O(logn) |
| upper_bound() | 第一個大於 | O(logn) |
依序給你n個數字,請你把重複的數字刪除,
並按照原本的順序印出
依序給你n個數字,請你把重複的數字刪除,
並按照原本的順序印出
ex
1 3 5 3 3 2 5 -> 1 3 2
順序跑過,對於每個數字,如果之前出現過,他就不能印出,否則印出
順序跑過,對於每個數字,如果之前出現過,他就不能印出,否則印出
SET !!!
Map
類似Python中的Dictionary
一個鍵(key)映射到一個值(value)
一個鍵(key)映射到一個值(value)
ex:
營養午餐 -> ㄆㄨㄣ
牛肉麵 -> delicious
泡麵 -> 便宜
| 名稱 | 功能 | 時間 |
|---|---|---|
| empty() | 回傳是否為空 | O(1) |
| size() | 大小 | O(1) |
| [key] = val | 插入元素 | O(logn) |
| erase() | 刪除元素 | O(logn) |
| find() | 是否找到元素 | O(logn) |
| count() | 是否找到元素 | O(logn) |
| lower_bound() | 第一個大於等於 | O(logn) |
| upper_bound() | 第一個大於 | O(logn) |
| [key] | 找到key對應的val | O(logn) |
給你n個數字,跟一個目標值k,
判斷是否存在n個數中的其中兩個和為k
若可以 -> 印出兩數字編號
否則 -> 印出 IMPOSSIBLE
n <= 200005
枚舉每兩個?
枚舉每兩個?
總共有 n^2 級別個數對 !
-> TLE
對於每個數字,我只要往前找是否有人跟他的和是k
對於每個數字,我只要往前找是否有人跟他的和是k
並且這個元素可能會被比他後面的元素找到
對於每個數字,我只要往前找是否有人跟他的和是k
並且這個元素可能會被比他後面的元素找到
因此我可以記下某些資訊以供人來找 ??
對於每個數字,我只要往前找是否有人跟他的和是k
並且這個元素可能會被比他後面的元素找到
因此我可以記下某些資訊以供人來找 ??
MAP !
如果我的值是 a
那我要找的人就是 (k-a)
如果我的值是 a
那我要找的人就是 (k-a)
因此每次先查找前面是否有 (k-a)
有的話就印出答案
否則
記錄下自己的值,給後人找 !
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 200005
int n,k;
map<int,int> mp;
main(){
cin>>n>>k;
for(int i=1;i<=n;++i){
int a; cin>>a;
if(mp.count(k-a)){
cout<<mp[k-a]<<' '<<i<<endl;
return 0;
}
mp[a] = i;
}
cout<<"IMPOSSIBLE"<<endl;
}AC code
Priority queue
優先的queue
優先的queue
每次拿出裡面的極值(max、min)
| 名稱 | 功能 | 時間 |
|---|---|---|
| empty() | 回傳是否為空 | O(1) |
| size() | 大小 | O(1) |
| push | 加入一新元素 | O(logn) |
| pop | 從後端刪除元素 | O(logn) |
| top | 回傳極值元素 | O(1) |
扣
#include<bits/stdc++.h>
using namespace std;
#define int long long
main(){
priority_queue<int> Q;
Q.push(64);
Q.push(2);
Q.push(9);
Q.push(3);
Q.push(65);
cout<<Q.top()<<endl;
Q.pop();
cout<<Q.top()<<endl;
cout<<Q.size()<<endl;
}有一根長度為x的棍子,我要把他切成n條棍子,
長度分別為d1、d2....dn,
每次可以把棍子切成兩半,成本為原棍子長度
ex :
長度為a的棍子切兩半cost = a
求最小cost
ex:
input :
8 3
2 3 3
output:
13
8
5
3
2
3
8
5
3
2
3
正的做好像有點難,那試試反著做 !
如果從下面合併上來
如果從下面合併上來
最終切成的棍子會造成多少COST ?
8
5
3
2
3
8
5
3
2
3
8
5
3
2
3
畫出來看看每段造成的 COST
8
5
3
2
3
畫出來看看每段造成的 COST
驚人發現長度為 X 的木棍對
COST的貢獻為 X * 深度(合併次數)
驚人發現長度為 X 的木棍對
COST的貢獻為 X * 深度(合併次數)
驚人發現長度為 X 的木棍對
COST的貢獻為 X * 深度(合併次數)
因此可以直觀的想到
由於合併次數固定
驚人發現長度為 X 的木棍對
COST的貢獻為 X * 深度(合併次數)
因此可以直觀的想到
由於合併次數固定
長度長的棍子合併少次一點
短的合併多次一點
因此可以每次合併長度最短的棍子
因此可以每次合併長度最短的棍子
如何找到最短的 ?
因此可以每次合併長度最短的棍子
如何找到最短的 ?
priority_queue !!!
code
#include<bits/stdc++.h>
using namespace std;
#define int long long
int x,n,as,a,l,r;
priority_queue<int,vector<int>,greater<int>> pq;
int main(){
cin>>x>>n;
for(int i=0;i<n;++i) {cin>>a; pq.push(a);}
while(pq.size()>1){
l = pq.top(); pq.pop();
r = pq.top(); pq.pop();
as += l+r;
pq.push(l+r);
}
cout<<as;
return 0;
}bitset
bool 陣列
bool 陣列
有什麼差 ?
bool arr[size]
bitset<size>
一個bool存的資訊
卻用到與int相同的空間 !?
一個bool存的資訊
卻用到與int相同的空間 !?
但bitset就是確確實實節省了許多空間
一個bool存的資訊
卻用到與int相同的空間 !?
但bitset就是確確實實節省了許多空間
因此只會用到 1/32 or 1/64 的記憶體空間
一個bool存的資訊
卻用到與int相同的空間 !?
但bitset就是確確實實節省了許多空間
因此只會用到 1/32 or 1/64 的記憶體空間
時間複雜度可以寫成O(n/w)
w = 32 or 64
有些題目就會這樣卡掉你
| 名稱 | 功能 | 時間 |
|---|---|---|
| .set(index,0or1) | index項設為1 | O(1) |
| .reset | 全部設為0 | O(n/w) |
| bitset & bitset | 每項取and | O(n/w) |
| bitset | bitset | 每項取or | O(n/w) |
| ~bitset | 每項取反 | O(n/w) |
| <<= k | 全部左移k | O(1) |
| >>= k | 全部右移k | O(1) |
| .count | 有幾個是1 | O(n/w) |
| .any | 有任何一個1 | O(1) |
| ._Find_next(index) | 下一個一的位置 | O(1) |
| ._Find_first(index) | 第一個1的位置 | O(1) |
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 200005
main(){
bitset<20> bt;
bt.set(10,1);
bt[11] = 1;
bt[12] = 1;
bt[13] = 1;
bt[17] = 1;
cout<<bt<<endl;
cout<<bt.count()<<endl;
bt >>= 5;
cout<<bt<<endl;
cout<<bt._Find_first()<<endl;
cout<<bt._Find_next(8)<<endl;
bt.set();// 什麼都不給,全部設為1
cout<<bt<<endl;
}algorithm
std sort
很快的排序
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 200005
main(){
int n,arr[maxn];
vector<int> v;
cin>>n;
for(int i=0;i<n;++i){
int a; cin>>a;
arr[i] = a;
v.push_back(a);
}
sort(arr,arr+n);
sort(v.begin(),v.end());
for(int i=0;i<n;++i) cout<<arr[i]<<' ';
}
如果想從大排到小 ?
如果想從大排到小 ?
greater !
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define maxn 200005
main(){
int n,arr[maxn];
vector<int> v;
cin>>n;
for(int i=0;i<n;++i){
int a; cin>>a;
arr[i] = a;
v.push_back(a);
}
sort(arr,arr+n,greater<int>());
sort(v.begin(),v.end(),greater<int>());
for(int i=0;i<n;++i) cout<<arr[i]<<' ';
}
雜談&小技巧
IO優化
有些題目你再怎麼寫,就是超時,輸入量又超過1e6級別時
有些題目你再怎麼寫,就是超時,輸入量又超過1e6級別時
不妨試試io優化
有些題目你再怎麼寫,就是超時,輸入量又超過1e6級別時
不妨試試io優化
也可以當成模板打
ios::sync_with_stdio(0);
cin.tie(0);
短短兩行就能大幅加速輸入
#include<bits/stdc++.h>
using namespace std;
main(){
ios::sync_with_stdio(0); cin.tie(0);
}用法就是直接打在main裡面
#include<bits/stdc++.h>
using namespace std;
main(){
ios::sync_with_stdio(0); cin.tie(0);
}用法就是直接打在main裡面
但要注意如果用了此優化,就不能混用cin、scanf
如何優化的??
如何優化的??
sync_with_stdio(0);
關閉 cin、cout、scanf、print的同步,
減少性能的損失
如何優化的??
sync_with_stdio(0);
關閉 cin、cout、scanf、print的同步,
減少性能的損失
也因此不能混用 cin、cout、scanf、print
如何優化的??
cin.tie(0);
當電腦執行cin時,會刷新輸出緩衝區,
確保了輸出在輸入之前完成,但耗費許多時間
如何優化的??
cin.tie(0);
當電腦執行cin時,會刷新輸出緩衝區,
確保了輸出在輸入之前完成,但耗費許多時間
因此cin.tie(0);
關閉了此動作,從而達到加速的效果
考一考大家
cpp有兩種換行方式:
endl
'\n'
哪一種比較快 ?
考一考大家
cpp有兩種換行方式:
endl
'\n'
哪一種比較快 ?
endl !
比較看看有什麼不同 !
#include<bits/stdc++.h>
using namespace std;
main(){
int n; cin>>n;
while(n--){
int a; cin>>a;
cout<<a<<'\n';
}
}#include<bits/stdc++.h>
using namespace std;
main(){
ios::sync_with_stdio(0); cin.tie(0);
int n; cin>>n;
while(n--){
int a; cin>>a;
cout<<a<<'\n';
}
}struct
假如我今天要記錄一個人的資訊
我可能要記 :
假如我今天要記錄一個人的資訊
我可能要記 :
性別
身高
體重
興趣
專長
............
假如我今天要記錄一個人的資訊
我可能要記 :
名字
性別
身高
體重
興趣
專長
............
一個變數存不下ㄚㄚㄚㄚㄚㄚ
這時,你就可以使用struct,想塞什麼就塞什麼
假設我要記錄一個人..
#include<bits/stdc++.h>
using namespace std;
struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
};
main(){
person a;
a.name = "蔡孟平";
a.hight = 200;
a.weight = 100;
a.gender = 1;
a.interest = "sleep";
a.expertise = "燒機";
cout<<a.name<<endl;
cout<<a.expertise<<endl;
}struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
};struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
};建立完struct後
直接把他當新的型別用
struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
};建立完struct後
直接把他當新的型別用
main(){
person a;
a.name = "蔡孟平";
a.hight = 200;
a.weight = 100;
a.gender = 1;
a.interest = "sleep";
a.expertise = "燒機";
cout<<a.name<<endl;
cout<<a.expertise<<endl;
}struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
};建立完struct後
直接把他當新的型別用
main(){
person a;
a.name = "蔡孟平";
a.hight = 200;
a.weight = 100;
a.gender = 1;
a.interest = "sleep";
a.expertise = "燒機";
cout<<a.name<<endl;
cout<<a.expertise<<endl;
}就像是piar有first、second
甚至可以...
struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
};
struct area{
string name;
int v,population;
vector<person> people;
};
struct nation{
vector<area> con;
string name;
};
如何初始化?
為什麼要初始化 ?
#include<bits/stdc++.h>
using namespace std;
struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
};
main(){
person A;
cout<<A.hight<<endl;
cout<<A.weight<<endl;
}
方法一
#include<bits/stdc++.h>
using namespace std;
struct person{
int hight = 0,weight = 0;
bool gender = 0;
string interest,expertise,name;
};
main(){
person A;
cout<<A.hight<<endl;
cout<<A.weight<<endl;
}方法二(比較常用)
#include<bits/stdc++.h>
using namespace std;
struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
person(int h,int w,bool g){
hight = h;
weight = w;
gender = g;
}
};
main(){
person A(100,100,1);
cout<<A.hight<<endl;
cout<<A.weight<<endl;
}方法二(比較常用)
還可以
#include<bits/stdc++.h>
using namespace std;
struct person{
int hight,weight;
bool gender;
string interest,expertise,name;
person(int h,int w,bool g){
hight = h;
weight = w;
gender = g;
}
person(){
hight = 1000000;
weight = 1000000;
gender = 1000000;
}
};
main(){
person A(100,100,1);
cout<<A.hight<<endl;
cout<<A.weight<<endl;
person B;
cout<<B.hight<<endl;
cout<<B.weight<<endl;
}
指標
指標就是
一個變數,但他存的東西是一個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;
}跑跑看
如何得到這個指標
所指到的,真正的值呢
如何得到這個指標
所指到的,真正的值呢
*
#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;
}因為指標是那個變數在記憶體中的位置
因此可以..
#include<bits/stdc++.h>
using namespace std;
int main(){
int a = 5;
int *ptr = &a;
cout<<a<<endl;
*ptr = 10;
cout<<a<<endl;
}直接殺到他家改
因為陣列的記憶體是連續的
所以...
#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;
}其實是一模一樣的東西
有什麼用 ?
reference
如果要寫一個含式,他的功能要能更改變數的值
你可能會 ...
#include<bits/stdc++.h>
using namespace std;
void oper(int tar,int val){
tar = val;
}
int main(){
int a = 99;
oper(a,5);
cout<<a<<endl;
}為什麼沒有改到 ?!?!
你可能會 ...
#include<bits/stdc++.h>
using namespace std;
void oper(int tar,int val){
tar = val;
}
int main(){
int a = 99;
oper(a,5);
cout<<a<<endl;
}為什麼沒有改到 ?!?!
你改的是副本 !!!
因此要傳變數本人進去 !!
#include<bits/stdc++.h>
using namespace std;
void oper(int &tar,int val){
tar = val;
}
int main(){
int a = 99;
oper(a,5);
cout<<a<<endl;
}小技巧
如果我想要指定輸出小數點後幾位怎麼辦?
如果我想要指定輸出小數點後幾位怎麼辦?
如果我想要指定輸出小數點後幾位怎麼辦?
cout<<fixed<<setprecision(位數);
int main(){
double a = 1243.4251;
cout<<a<<endl;
cout<<fixed<<setprecision(10);
cout<<a<<endl;
}我好懶,不想自己寫型別
我好懶,不想自己寫型別
沒關係 ! 可以用auto,丟給編譯器弄
#include<bits/stdc++.h>
using namespace std;
int main(){
auto a = 938479832.23498273;
auto b = 8493794;
auto c = 8493547324235432944;
cout<<typeid(a).name()<<endl;
cout<<typeid(b).name()<<endl;
cout<<typeid(c).name()<<endl;
}
Bento
By maxbrucelen
Bento
- 412