寒假训练十(map,pair,string)2020.02.17(4题)
寒假訓練十(map) id:535
Problem:A 保齡球-map
Description
DL 算緣分算得很煩悶,所以常常到體育館去打保齡球解悶。因為他保齡球已經打了幾十年了,所以技術上不成問題,于是他就想玩點新花招。
DL 的視力真的很不錯,竟然能夠數清楚在他前方十米左右每個位置的瓶子的數量。他突然發現這是一個炫耀自己好視力的借口——他看清遠方瓶子的個數后從某個位置發球,這樣就能打倒一定數量的瓶子。
1 OOO
2 OOOO
3 O
4 OO
如上圖,每個“O”代表一個瓶子。如果 DL 想要打倒 3 個瓶子就在 1 位置發球,想要打倒 4 個瓶子就在 2 位置發球。
現在他想要打倒 m 個瓶子。他告訴你每個位置的瓶子數,請你給他一個發球位置。
Input
第一行包含一個正整數 n,表示位置數。
第二行包含 n 個正整數,第 i 個數。表示第 i 個位置的瓶子數,保證各個位置的瓶子數不同。
第三行包含一個正整數 Q,表示 DL 發球的次數。
第四行至文件末尾,每行包含一個正整數 m,表示 DL 需要打倒 m 個瓶子。
Output
共 Q 行。每行包含一個整數,第 i 行的整數表示 DL 第 i 次的發球位置。若無解,則輸出 0。
Sample Input
5 1 2 4 3 5 2 4 7Sample Output
3 0Hint
【數據范圍】
對于 50%的數據,1 ≤ n,Q ≤ 1000,1 ≤ai,M ≤ 10^5
對于 100%的數據,1 ≤ n,Q ≤ 100000,1 ≤ai,M ≤ 10^9
code
#include<bits/stdc++.h> using namespace std; map<int,int>v; int main() {ios::sync_with_stdio(false);int n,m,x,q,f;cin>>n;for(int i=1;i<=n;i++){cin>>x;v[x]=i;}cin>>q;while(q--){cin>>m;cout<<v[m]<<endl;}return 0; }其實用cout的話即使取消同步也會超時,太魔幻了......
Problem:B 查字典
Description
小明正在復習全國英語四級考試,他手里有一本詞典,現在有很多單詞要查。請編寫程序幫助他快速找到要查的單詞所在的頁碼。
Input
第 1 行 1 個正整數 N,N≤10000,表示字典中一共有多少單詞。
接下來每兩行表示一個單詞,其中:
第 1 行是一個長度小于或等于 100 的字符串,表示這個單詞,全部小寫字母,單詞不會重復。
第 2 行是 1 個整數,表示這個單詞在字典中的頁碼。
接下來的一行是 1 個整數 M,M≤10000,表示要查的單詞數。接下來的 M 行,每行一個字符串,表示要查的單詞,保證在字典中存在。
Output
M 行,每行一個正整數,表示第 i 個單詞在字典中的頁碼。
Sample Input
2 scan 10 word 15 2 scan wordSample Output
10 15code
#include<bits/stdc++.h> using namespace std; map<string,int>vis; int main() {int n,m,x,y;string w;cin>>n;while(n--){cin>>w>>x;vis.insert(pair<string, int>(w,x));}cin>>m;while(m--){cin>>w;cout<<vis[w]<<endl;}return 0; }Problem:C 眼紅的Medusa
Description
雖然Miss Medusa到了北京,領了科技創新獎,但是他還是覺得不滿意。原因是,他發現很多人都和他一樣獲了科技創新獎,特別是其中的某些人,還獲得了另一個獎項——特殊貢獻獎。而越多的人獲得了兩個獎項,Miss Medusa就會越眼紅。于是她決定統計有哪些人獲得了兩個獎項,來知道自己有多眼紅。
Input
輸入第一行,有兩個數n,m,表示有n個人獲得科技創新獎,m個人獲得特殊貢獻獎。
第二行,n個正整數,表示獲得科技創新獎的人的編號
第三行,m個正整數,表示獲得特殊貢獻獎的人的編號
Output
輸出一行,為獲得兩個獎項的人的編號,按在科技創新獎獲獎名單中的先后次序輸出。
注意:本題答案輸出一行,最后不需要換行,否則會Presentation Error
Sample Input
4 3
2 15 6 8
8 9 2
Sample Output
2 8
Hint
對于60%的數據,n<=1000,m<=1000
對于100%的數據,n<=100000,m<=100000,獲得獎項的人的編號在2e9以內
輸入數據保證第二行任意兩個數不同,第三行任意兩個數不同。
code
#include<bits/stdc++.h> using namespace std; int n,m; map<int,int> vis; int a[111111],b[111111]; int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=m;i++){scanf("%d",&b[i]);vis[b[i]]=1;//用b[i]捋一遍,獲獎則設為真}for(int i=1;i<=n;i++)if(vis[a[i]])//再用a[i]訪問一遍,//訪問到的自然都獲獎a,為真的則獲兩獎cout<<a[i]<<" "; return 0; }Problem:D 指數序列
Description
伊凡在紙上寫下了一個由 n 個非負整數組成的序列 a1 ,a2 ,…,an 。這個序列保證單調不降。
接著,伊凡又在紙上寫下了另一個序列 2^a1 ,2^a2 ,…,2^an 。現在他想知道,最少要在這個序列中添加多少個形式為 2^x 的數(x 為非負整數),才能使這個序列所有整數的和為 2^v-1 ,其中 v 為某個非負整數。
Input
(單組輸入)
第 1 行包括 1 個正整數 n(1≤n≤1e5 )。
第 2 行包括 n 個由空格隔開的整數a1 ,a2 ,…,an 。其中,0≤ai ≤2×10^9 ,保證 a1 ≤a2 ≤…≤an 。
Output
輸出一行一個整數,表示最少在序列中添加數的數量。
Sample Input
4
0 1 1 1
Sample Output
0
Hint
在第1個樣例中不需要添加任何數,因為20+21+21+21 =1+2+2+2=7=2^3-1。
code
#include<bits/stdc++.h> using namespace std; int n,ans; int main(){cin>>n;long long s=0;for(int i=1;i<=n;i++){int t;cin>>t;s +=(1<<t);}while(s){int t=s%2;s/=2;if(t==0) ans++;} printf("%d\n",ans);return 0;}第二天學了set,又看了看學長的博客,發現還能這么用
#include <bits/stdc++.h> using namespace std; int n,x,s,mx; set<int>ans; map<int,int>vis; int main() {ios::sync_with_stdio(false);cin>>n;for(int i=1;i<=n;i++){cin>>x;vis[x]++;ans.insert(x);mx=max(mx,x);}for(set<int>::iterator it=ans.begin();it!=ans.end();it++){x=*it;int tmp=vis[x];vis[x]=tmp%2;if(vis[x]==0)s++;//統計被刪除的數的個數int k=tmp/2;//將相同的兩個數合并,合并后的數大小+1,個數+kif(!vis[x+1]&&k!=0){ans.insert(x+1);//合并后的數大小+1mx=max(mx,x+1);//mx記錄合并完成后數的最大值}vis[x+1]+=k;//合并后的數的個數+k}printf("%d\n",mx+1-ans.size()+s);return 0; }總結
1.map的定義
map<typename1,typename2> name;map在建立映射的同時,會自動按照鍵key從小到大排序。
map的二維表示
map<int,map<int,int> >vis; map<pair<int,int>,int>vis;2.map的訪問
訪問 map 的元素有兩種方式,一種是通過下標訪問;另一種是通過迭代器訪問。
通過下標訪問就像普通的數組元素訪問,例如先定義map<char,int> mp,然后就可以通過mp[‘c’]的方式來訪問它對應的元素,如mp[‘c’]=124。
通過迭代器訪問,先作如下定義:
map<typename1,typename2>::iterator it;因為map的每一對映射都有兩個typename,所以,我們使用“it->first”來訪問鍵,而使用“it->second”來訪問值。
map<typename1, typename2>::iterator it; int main() {map<char, int> mp;mp['m'] = 20;mp['r'] = 30;mp['a'] = 40;for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it++) {printf("%c %d\n", it -> first, it -> second);}return 0; }3.map 的常用函數
(1)find()和 size()
find(key)是返回鍵為 key 的映射的迭代器,時間復雜度為 0(log 2 n),n 為 map 中映射的對數。size()用來獲得map中映射的對數,時間復雜度為O(1)。
(2)clear()
clear()用來清空 map,時間復雜度為 0(n)。
(3)erase()
erase()可以刪除單個元素,也可以刪除一個區間內的所有元素。
刪除單個元素可以用:erase(it),it為要刪除的元素的迭代器,時間復雜度為O(1)。
也可以用:erase(key),key為要刪除的映射的鍵,時間復雜度為O(log2n)。
刪除一個區間內的所有元素用:erase(first,last),first為區間的起始迭代器,last為區間的末尾迭代器的下一個地址,也就是左閉右開的區間[first,last),時間復雜度為O(last-first)。
4.pair的定義
pair 是“二元結構體”的替代品,將兩個元素捆綁在一起,節省編碼時間。
pair<typename1,typename2> name; struct pair{typename1 first;typename2 second; }; //這兩個定義是一樣的5.string的訪問
一種訪問 string 的方法,就像普通字符數組一樣操作。如:
string str= “ abcd “ ; for(int i = 0; i < str.length(); i++) printf( “ %c “ ,str[i]); // 輸出 abcd如果要讀入或者輸出整個字符串,一般只能用cin和cout。
如果非要用printf輸出string,則需要用c_str()函數將string轉換成字符數組。如:
總結
以上是生活随笔為你收集整理的寒假训练十(map,pair,string)2020.02.17(4题)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux so_linger,linu
- 下一篇: 山东理工大学单元测试2重现