日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【计蒜客 - 蓝桥训练】轻重搭配(贪心,STLset 或 二分)

發布時間:2023/12/10 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【计蒜客 - 蓝桥训练】轻重搭配(贪心,STLset 或 二分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題干:

n?個同學去動物園參觀,原本每人都需要買一張門票,但售票處推出了一個優惠活動,一個體重為?xx?的人可以和體重至少為?2x2x?配對,這樣兩人只需買一張票?,F在給出了?nn?個人的體重,請你計算他們最少需要買幾張門票?

輸入格式

第一行一個整數?nn,表示人數。

第二行?nn?個整數,每個整數?a_iai??表示每個人的體重。

輸出格式

一個整數,表示最少需要購買的門票數目。

數據范圍

對于?30\%30%?的數據:1 \le n \le 251≤n≤25,1\le a_i \le 1001≤ai?≤100。

對于?60\%60%?的數據:1 \le n \le 100001≤n≤10000,1\le a_i \le 10001≤ai?≤1000。

對于?100\%100%?的數據:1 \le n \le 5\cdot 10^51≤n≤5?105,1\le a_i \le 10^51≤ai?≤105。

樣例解釋

11?和?99?配對,77?和?33?配對,剩下?5,55,5?單獨,一共買四張票。

樣例輸入復制

6 1 9 7 3 5 5

樣例輸出復制

4

解題報告:

? ? 這題貪心證明(同優則立法),一定可以從前n/2個數中選擇就行了,然后從后面剩下的數(可能n/2 也可以 n/2 +1)中選擇配對的。。

錯誤代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; set<int> ss; set<int> :: iterator it,itt; int main() {int n;cin>>n;for(int tmp,i = 1; i<=n; i++) {scanf("%d",&tmp);ss.insert(tmp);}int ans = 0;while(ss.size()) {it = ss.begin();itt = ss.lower_bound(*it * 2);if(itt == ss.end()) break;else ss.erase(itt),ss.erase(it),ans++;}cout << ss.size() + ans << endl;return 0 ;} /* 6 1 3 5 5 7 9 */

一改:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; int a[MAX]; set<int> ss; set<int> :: iterator it; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) {scanf("%d",a+i);}sort(a+1,a+n+1);for(int i = n/2+1; i<=n; i++) {ss.insert(a[i]);}int cur = 1;while(ss.size() && cur <= n/2) {it = ss.lower_bound(a[cur] * 2); // printf("it = %d\n",*it);if(it == ss.end()) break;else ss.erase(it);cur++;}cur--;cout << /*ss.size() + n/2 - cur*/n-cur << endl;return 0 ;} /* 6 1 3 5 5 7 9 */

AC代碼:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 6e5 + 5; int a[MAX]; multiset<int> ss; multiset<int> :: iterator it; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) {scanf("%d",a+i);}sort(a+1,a+n+1);for(int i = n/2+1; i<=n; i++) {ss.insert(a[i]);}int ans = 0;int cur = 1;while(ss.size() && cur <= n/2) {it = ss.lower_bound(a[cur] * 2); // printf("it = %d\n",*it);if(it == ss.end()) break;else ss.erase(it),ans++;cur++;}cur--;cout << ans + (n/2 - cur) + ss.size() << endl;return 0 ;} /* 6 1 3 5 5 7 9 */

注意點:最后答案的計算,來自三部分別忘了(其實根據標程那個想法更好想)。

? cur從1開始而非從0開始。

? ?用multiset,而不是set。

? 還有一個坑點,,數據范圍是5e5,,我一般習慣2e5了,,所以一直WA。。

或者最后答案這么計算:

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 6e5 + 5; int a[MAX]; multiset<int> ss; multiset<int> :: iterator it; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) {scanf("%d",a+i);}sort(a+1,a+n+1);for(int i = n/2+1; i<=n; i++) {ss.insert(a[i]);}int cur = 1;while(ss.size() && cur <= n/2) {it = ss.lower_bound(a[cur] * 2); // printf("it = %d\n",*it);if(it == ss.end()) break;else ss.erase(it);cur++;}cur--;cout << /*ss.size() + n/2 - cur*/n-cur << endl;return 0 ; } /* 6 1 3 5 5 7 9 */

標準的SET的AC代碼(233ms):

#include <algorithm> #include <iostream> #include <set> using namespace std; int a[1000005]; int main() {int n;scanf("%d", &n);for (int i = 0; i < n; i++) {scanf("%d", &a[i]);}sort(a, a + n);multiset<int> se;for (int i = n / 2; i < n; i++) {se.insert(a[i]);}int ans = n;for (int i = 0; i < n / 2; i++) {multiset<int>::iterator it = se.lower_bound(a[i] * 2);if (it == se.end()) break;se.erase(it);ans--;}printf("%d\n", ans);return 0; }

另一個線性的做法(不用SET的標程82ms):

#include <algorithm> #include <cstdio> using namespace std; int a[500005]; int main() {int n;scanf("%d", &n);for (int i = 0; i < n; i++) {scanf("%d", &a[i]);}sort(a, a + n);int ans = n, pos = n / 2;for (int i = 0; i < n / 2; i++) {while (pos < n && a[pos] < a[i] * 2) pos++;if (pos == n) break;ans--;pos++;}printf("%d\n", ans);return 0; }

這題還可以二分:

后來就想到,如果某種方案配對了x對,那么我們可以統一將這x對中比較大的數字,從大到小依次用a[n],a[n-1]……a[n-x+1]給替換掉;而比較小的數字從小到大依次用a[1]……a[x]替換掉,可知替換出來還是滿足條件的方案。另外我們將每一對視作一條邊,連接小數字的有序數列和大數字的有序數列,那么會產生一個二分圖。
?如果兩條邊出現交叉,也就是出現a[i]<a[j], a[ii]>a[jj],a[i]*2<=a[ii],a[j]*2<=a[jj]。那么可以將i連接jj而j連接ii。經過一陣重新連接,我們發現,可能的方案等價于a[1]連接a[n-x+1]……a[x]連接a[n],于是現在我們只需要找出具體對于哪個x成立就行了,所以對于這種,已知答案就可以推算是否合理的題目,我們選擇二分。

#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair using namespace std; const int MAX = 6e5 + 5;int a[MAX],n;bool ok(int x) {for(int i = 1; i<=x; i++) {if(a[i+n-x]<a[i]*2) return 0;}return 1; }int main() {cin>>n;for(int i = 1; i<=n; i++) scanf("%d",a+i);sort(a+1,a+n+1);int l=0,r=n/2,mid,ans=0;while(l<=r){mid = (l+r)>>1;if(ok(mid)) l=mid+1,ans=mid;else r=mid-1;}printf("%d",n-ans);return 0; }

?

總結

以上是生活随笔為你收集整理的【计蒜客 - 蓝桥训练】轻重搭配(贪心,STLset 或 二分)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。