吉林区域赛 C - Justice 模拟

链接:https://vjudge.net/contest/386991#problem/C

题意:给出2指数级倍数的倒数

   让我们把这些数分为两个堆,看看能不能分别分出两个大于等于二分之一的堆

思路:用优先队列+并查集的方式

   优先队列从大到小排序,然后每次取最大的两个数进行操作,如果两个数不同,则剔除最大的那个数,继续循环

           如果相同,就合并,然后用并查集把这两个数的下标归到同一个区间  

           然后再把合并后的数放到优先队列里,新的数沿用合并数的下标,然后再操作即可。

   直到遇到了1,或者队列大小小于2

   但是有一个细节问题:假如一开始就有两个1的话,我们就直接另类讨论即可。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5+10;
 4 int f[maxn];
 5 int a[maxn];
 6 struct node
 7 {
 8     int val;
 9     int index;
10     friend bool operator <(const node &a,const node &b){
11         return a.val<b.val;
12     }
13 };
14 priority_queue<node>Q;
15 int getf(int u)
16 {
17     if(u==f[u]) return u;
18     f[u]=getf(f[u]);
19     return f[u];
20 }
21 void Union(int u,int v)
22 {
23     if(u>v) swap(u,v);
24     int t1=getf(u);
25     int t2=getf(v);
26     if(t1!=t2){
27         f[t2]=t1;
28     }
29 }
30 int main()
31 {
32     int T;
33     scanf("%d",&T);
34     int Case=0;
35     while(T--){
36         int n;
37         scanf("%d",&n);
38         //init
39         for(int i=1;i<=n;i++) f[i]=i;
40         while(!Q.empty()) Q.pop();
41         //init
42         node tmp;
43         int sum=0;
44         int base=0;
45         for(int i=1;i<=n;i++){
46             scanf("%d",&tmp.val);
47             tmp.index=i;
48             if(tmp.val==1){
49                 sum++;
50                 base=i;
51             }
52             Q.push(tmp);
53         }
54         if(sum>=2){
55             printf("Case %d: YES\n",++Case);
56             int flag=0;
57             for(int i=1;i<=n;i++){
58                 if(i==base){
59                     printf("1");
60                 }
61                 else printf("0");
62             }
63             printf("\n");
64             continue;
65         }
66         node a,b;
67         while(Q.size()>=2){
68             a=Q.top();
69             if(a.val==1){
70                 break;
71             }
72             Q.pop();
73             b=Q.top();
74             if(a.val==b.val){
75                 Union(a.index,b.index);
76                 Q.pop();
77                 a.val-=1;
78                 Q.push(a);
79             }
80         }
81         a=Q.top();
82         if(Q.size()>=2&&a.val==1){
83             printf("Case %d: YES\n",++Case);
84             int flag=getf(a.index);
85             for(int i=1;i<=n;i++){
86                 if(flag==getf(i)){
87                     printf("1");
88                 }
89                 else printf("0");
90             }
91             printf("\n");
92         }
93         else{
94             printf("Case %d: NO\n",++Case);
95         }
96     }
97     return 0;
98 }

 

上一篇:【并查集】关押罪犯 C++题解


下一篇:1387. 将整数按权重排序