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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CodeForces - 468B Two Sets(并查集+思维)

發布時間:2024/4/11 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces - 468B Two Sets(并查集+思维) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:現在給出兩個集合A和B,再給出兩個數a和b,現在規定在集合A中的數x必須滿足x和a-x同時在集合a中,而在集合B中的數x也同樣需要滿足x和b-x同時在集合B中,現在給出一系列數,問能否將所有的數都分配到兩個集合中去

題目分析:這個題因為放在了二分圖的專題里,所以一開始想盡了一切辦法想將這個題目往匈牙利上靠攏,但最終沒辦法將模型抽象出來,看了題解后才知道是個簡單并查集的題目,這里分析一下吧,對于任意一個x,無非只有四種情況:

  • a-x不存在,b-x不存在:輸出NO
  • a-x存在,b-x不存在:將x放到集合A中
  • a-x不存在,b-x存在:將x放到集合B中
  • a-x存在,b-x存在:將x放到集合A和集合B中
  • 因為給出的n個數兩兩都是不同的,并且都是正整數,所以我們可以在一開始的時候就剪一下枝,如果數列中的最大值大于等于a或b中的最大值顯然是輸出NO的,因為這個時候無論是a還是b,減去這個最大值一定是一個負數,肯定找不到與其對應的一個正整數,這種情況可以歸類為上面所述的第一種情況

    我們維護1~n為數列,然后0為集合A,n+1為集合B,在輸入的時候就用map維護每個數的下標,最后遍歷一遍,按照上述的2-4規則用并查集維護一下下標,將x和a-x建邊或x和b-x建邊,最后判斷即可

    該怎么判斷呢?因為如果滿足了第一種情況,也就是a-x和b-x在數列中都不存在的話,那么這個數肯定被else判斷到了兩個集合中去了,也就是將點0和點n+1建了一條邊,第二種情況和第三種情況都會根據巧妙的邏輯將其與相應的集合建邊,不重不漏,最后如果都存在的話,則只會先將這三個點:x,a-x,b-x三點建邊,等到后續判斷a-x的時候,以及b-x的時候,再利用else的邏輯將其與相應集合建邊

    不得不佩服這個題的思維邏輯

    代碼:

    #include<iostream> #include<cstdlib> #include<string> #include<cstring> #include<cstdio> #include<algorithm> #include<climits> #include<cmath> #include<cctype> #include<stack> #include<queue> #include<list> #include<vector> #include<set> #include<map> #include<sstream> #include<unordered_map> using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int val[N];unordered_map<int,int>pos;int f[N];int find(int x) {return x==f[x]?x:f[x]=find(f[x]); }void merge(int x,int y) {int xx=find(x);int yy=find(y);f[xx]=yy; }int main() { // freopen("input.txt","r",stdin); // ios::sync_with_stdio(false);int n,a,b;scanf("%d%d%d",&n,&a,&b);int mmax=0;for(int i=1;i<=n;i++){scanf("%d",val+i);pos[val[i]]=i;mmax=max(mmax,val[i]);}if(mmax>=max(a,b))return 0*printf("NO\n");for(int i=0;i<=n+1;i++)f[i]=i;for(int i=1;i<=n;i++){if(pos[a-val[i]])//如果x與a-x有對應,就建邊merge(i,pos[a-val[i]]);else//否則將x加入到集合B中去merge(i,n+1);if(pos[b-val[i]])//如果x與b-x有對應,就建邊merge(i,pos[b-val[i]]);else//否則將x加入到集合A中去merge(i,0);}int A=find(0);int B=find(n+1);if(A==B)printf("NO\n");else{printf("YES\n");for(int i=1;i<=n;i++){if(find(i)==A)printf("0");elseprintf("1");if(i!=n)putchar(' ');elseputchar('\n');}}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的CodeForces - 468B Two Sets(并查集+思维)的全部內容,希望文章能夠幫你解決所遇到的問題。

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