CF468B Two Sets
生活随笔
收集整理的這篇文章主要介紹了
CF468B Two Sets
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
原題鏈接
DOWNLOAD AS PDF
題目大意
給出\(n\)個各不相同的數字,將它們分別放入\(A\)和\(B\)兩個集合中,使它們滿足:
- 若數字\(x\)在集合\(A\)中,那么數字\(a-x\)也在集合\(A\)中;
- 若數字\(x\)在集合\(B\)中,那么數字\(b?x\)也在集合\(B\)中。
(by \(\color{red}\sf{Uranus}\))
題解
感覺網上全是并查集的題解。
沒有貪心?
感覺貪心比并查集好想啊……
首先我們想到的肯定是開個set大力匹配,然而發現對于一個\(x\)可能\(a-x\)和\(b-x\)都在序列中,于是我們就陷入兩難了。
如何解決這個問題呢?
現在我們假設\(a\ge b\)。
我們每次貪心地選出沒有匹配過的數的最小值,設其為\(x\)。
假設我們發現\(a-x\)和\(b-x\)都在序列中且都沒有被匹配過。
我們會發現\(x\)一定與\(a - x\)匹配。
假設答案是\(x\)與\(b - x\)匹配,那也就是說\(a - x\)不在\(A\)集合里,所以其在\(B\)集合里,則與之匹配的是\(b - (a - x) = x + (b - a)\le x\),但由于\(x\)是序列中的最小數,所以不存在\(b - (a - x)\)。
代碼也很簡單:
#include <cstdio> #include <cstring> #include <set>using namespace std;const int maxn = 100005;int ans[maxn];struct EE {int x, id;inline bool operator < (const EE& other) const{return this->x < other.x;} } aa[maxn];set<EE> ss;int main() {int n, a, b;scanf("%d%d%d", &n, &a, &b);ss.clear();bool f = false;if(a < b){swap(a, b);f = true;}for(int i = 1; i <= n; ++i){EE aa;scanf("%d", &aa.x);aa.id = i;ss.insert(aa);}memset(ans, 0xff, sizeof(ans));while(!ss.empty()){set<EE>::iterator it = ss.begin();EE tx = *it;tx.x = a - it->x;set<EE>::iterator x = ss.lower_bound(tx);if(x != ss.end() && x->x + it->x == a){ans[x->id] = ans[it->id] = 0;if(x->id != it->id){ss.erase(x);ss.erase(it);}elsess.erase(x);}else{tx.x = b - it->x;x = ss.lower_bound(tx);if(x != ss.end() && x->x + it->x == b){ans[x->id] = ans[it->id] = 1;if(x->id != it->id)ss.erase(it);ss.erase(x);}elsereturn puts("NO"), 0;}}puts("YES");for(int i = 1; i <= n; ++i)printf("%d ", ans[i] ^ f);return 0; }轉載于:https://www.cnblogs.com/pfypfy/p/9609913.html
總結
以上是生活随笔為你收集整理的CF468B Two Sets的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: LOJ#6002. 「网络流 24 题」
- 下一篇: 最优化课堂笔记08——非线性规划中的一些