【CodeForces - 798D】Mike and distribution (思维构造,贪心,黑科技)
題干:
Mike has always been thinking about the harshness of social inequality. He's so obsessed with it that sometimes it even affects him while solving problems. At the moment, Mike has two sequences of positive integers?A?=?[a1,?a2,?...,?an]?and?B?=?[b1,?b2,?...,?bn]?of length?n?each which he uses to ask people some quite peculiar questions.
To test you on how good are you at spotting inequality in life, he wants you to find an?"unfair"?subset of the original sequence. To be more precise, he wants you to select?k?numbers?P?=?[p1,?p2,?...,?pk]?such that?1?≤?pi?≤?n?for?1?≤?i?≤?k?and elements in?P?are distinct. Sequence?P?will represent indices of elements that you'll select from both sequences. He calls such a subset?P?"unfair"?if and only if the following conditions are satisfied:?2·(ap1?+?...?+?apk)?is?greater?than the sum of all elements from sequence?A, and?2·(bp1?+?...?+?bpk)?is?greater?than the sum of all elements from the sequence?B. Also,?k?should be smaller or equal to??because it will be to easy to find sequence?P?if he allowed you to select too many elements!
Mike guarantees you that a solution will always exist given the conditions described above, so please help him satisfy his curiosity!
Input
The first line contains integer?n?(1?≤?n?≤?105) — the number of elements in the sequences.
On the second line there are?n?space-separated integers?a1,?...,?an?(1?≤?ai?≤?109) — elements of sequence?A.
On the third line there are also?n?space-separated integers?b1,?...,?bn?(1?≤?bi?≤?109) — elements of sequence?B.
Output
On the first line output an integer?k?which represents the size of the found subset.?k?should be less or equal to?.
On the next line print?k?integers?p1,?p2,?...,?pk?(1?≤?pi?≤?n) — the elements of sequence?P. You can print the numbers in any order you want. Elements in sequence?Pshould be distinct.
Example
Input
5 8 7 4 8 3 4 2 5 3 7Output
3 1 4 5題目大意:
麥克有兩個只包含正整數的數組?A?=?[a1,?a2,?...,?an]?和?B?=?[b1,?b2,?...,?bn]?,長度都為?n?。
他現在想要選出?k?個數?P?=?[p1,?p2,?...,?pk]?滿足?1?≤?pi?≤?n?并且數組?P?中的數字互不相等。要求P數組滿足:?2·(ap1?+?...?+?apk)?比數組?A?的和大,并且?2·(bp1?+?...?+?bpk)?比數組?B的和大。當然,?k?必須小于等于???,否則?P?數組太容易選出來了。
請你給出一個合法的方案。
解題報告:
? ? ?這題顯然要貪心,,但是貪心還是有技巧的。。首先我們發現選擇的數量當然是越多越好,所以我們肯定要選滿n/2+1個數。
? ? ?預處理一波,讀入的時候a和b捆綁讀入,,因為他倆要選就是一起選。。這很套路了不說了。
? ? ?首先按照a數組排序,,然后把所有的數字分成兩組,,轉化問題變成:使得選出的數分別在兩個數組中的和,大于剩下沒有選的數的和。我們發現這只是個充分條件,,并不是充分必要條件,也就是說條件加強了 ,但是我們發現對于這道題加強這一步條件后恰好可以構造出一組解。
? ? ?我們將其兩兩相鄰的數分成一組,每次從這一組中取出一個就行了,所以我們貪心處理只要拿b值較大的那一個即可,因為a肯定是滿足遞減的也就是不管我們這兩個拿哪一個a,都可以干掉下一組的選擇的那個a。
? ? 這就很美滋滋了,,仔細觀察可以發現,其實對于a數組是跨組貪心的,,也就是我們是這一組取一個值,讓他大于下一組的值;對于b數組是本組貪心的,,也就是我們選擇的這一個? 一定是本組的最優。
? ? 所以對于這種貪心策略,我們只需要再找一個大于第一組的選擇的a就行了(因為不然沒有人壓過他),對于這種特例我們這樣處理:排好序后第一個結構體一定是我們選擇的,然后從第二個元素開始往后分組,,這樣就有一個好處那就是可以保證后面的貪心一定是正確的,并且我們也有一個元素可以壓過第一組的a。。所以貪心結束。寫代碼就完事了。
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 = 2e5 + 5; struct Node {int a,b;int pos; } node[MAX]; bool cmp (Node a,Node b) {if(a.a != b.a) return a.a > b.a;else return a.b > b.b; } int ans[MAX]; int main() {int n;cin>>n;for(int i = 1; i<=n; i++) scanf("%d",&node[i].a),node[i].pos = i;for(int i = 1; i<=n; i++) scanf("%d",&node[i].b);sort(node+1,node+n+1,cmp);int tot = 0;ans[++tot] = node[1].pos;for(int i = 2; i<=n; i+=2) {if(node[i].b >= node[i+1].b) ans[++tot] = node[i].pos;else ans[++tot] = node[i+1].pos;}//if(n%2==0) ans[++tot] = n;printf("%d\n",tot);for(int i = 1; i<=tot; i++) printf("%d%c",ans[i],i == tot ? '\n' : ' ');return 0 ;}總結:
? 這題思維很巧妙啊。。分成兩組,,將問題轉化成一個充分條件的問題去進行求解,因為這樣方便我們構造貪心。還是要從條件入手啊,,告訴你選n/2個數了,分析一下,,也只能分成兩組去考慮 這么做了。
20191005陳題重做
再來介紹一種黑科技:
random_shuffle(R+1,R+n+1);可以在O(n)的時間內獲得一個隨機排列。
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<stack> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define FF first #define SS second #define ll long long #define pb push_back #define pm make_pair using namespace std; typedef pair<int,int> PII; const int MAX = 2e5 + 5; int n,up; struct Node {int a,b,id; } R[MAX]; ll suma,sumb; bool ok() {ll ta = 0,tb = 0;for(int i = 1; i<=up; i++) {ta += R[i].a;tb += R[i].b; }if(ta*2>suma && tb*2>sumb) return 1;else return 0; } int main() {cin>>n;for(int i = 1; i<=n; i++) cin>>R[i].a,R[i].id=i,suma += R[i].a;for(int i = 1; i<=n; i++) cin>>R[i].b,sumb += R[i].b;up = n/2+1;printf("%d\n",up);while(1) {random_shuffle(R+1,R+n+1);if(ok()) break;}for(int i = 1; i<=up; i++) printf("%d ",R[i].id);return 0 ; }?
總結
以上是生活随笔為你收集整理的【CodeForces - 798D】Mike and distribution (思维构造,贪心,黑科技)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【CodeForces - 670D1
- 下一篇: 存款利率连续三个月上涨,3年期的涨幅最大