【HDU - 6557】Justice(思维,模拟,套路,SETset)

230 篇文章 1 订阅

题干:

On the table there are n weights. On the body of the i-th weight carved a positive integer kiki , indicating that its weight is 12ki12ki gram. Is it possible to divide the n weights into two groups and make sure that the sum of the weights in each group is greater or equal to 1212 gram? That’s on your call. And please tell us how if possible.

Input

In the first line of the input there is a positive integer TT (1 ≤ TT ≤ 2000), indicating there are TT testcases.
In the first line of each of the TT testcases, there is a positive integer nn (1 ≤ nn ≤ 105105, ∑n ≤ 7 × 105105), indicating there are nn weights on the table.
In the next line, there are nn integers kiki (1 ≤ ki ≤ 109109), indicating the number carved on each weight.

Output

For each testcase, first print Case ii: ANSWER in one line, ii indicating the case number starting from 11 and ANSWER should be either YES or NO, indicating whether or not it is possible to divide the weights. Pay attention to the space between : and ANSWER.
If it’s possible, you should continue to output the dividing solution by print a 0/1 string of length nn in the next line. The ii-th character in the string indicating whether you choose to put the i-th weight in group 0 or group 1.

Sample Input

3
3
2 2 2
3
2 2 1
2
1 1

Sample Output

Case 1: NO
Case 2: YES
001
Case 3: YES
10

题目大意:

给你 n 个数,如果这个数是k,代表的权值为 \frac{1}{2^{k}}。让你把 n 个数分成两堆,其中每一堆权值和大于等于 1/2。n<1e5, ai<1e9。

要求输出是否可以凑出来,如果可以,要求输出每个数属于哪一个集合,让你输出0或者1。

解题报告:

已经变成了套路题。容易发现两个k可以合成为k-1,所以题意转换一下:按照上述合并规则,答案有解当且仅当可以合成两个1。

所以直接贪心,从小到大搞就好了,拿个set在线维护出现的元素。从大到小搞应该也是可以的,但是不能不排序就乱搞。

之前出现过的类似题有:【CodeForces - 988C 】Equal Sums

AC代码:

#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;
set<int> ss;
struct Node {
    int a,id;
    bool operator<(const Node & b) const {
        return a < b.a;
    }
} R[MAX];
int tmp,n,tar,ans[MAX];
int main()
{
    int T,iCase=0;
    cin>>T;
    while(T--) {
        scanf("%d",&n);ss.clear();tar=-1;
        for(int i = 1; i<=n; i++) scanf("%d",&R[i].a),R[i].id = i,ans[i]=0;
        printf("Case %d: ",++iCase); 
        sort(R+1,R+n+1);
        for(int i = 1; i<=n; i++) {
            tmp=R[i].a;ans[R[i].id] = 1;
            while(ss.count(tmp) && tmp >= 2) ss.erase(tmp),tmp--;
            ss.insert(tmp);
            if(tmp == 1) {tar = i+1;break;}
        }
        if(tar==-1) {puts("NO");continue;}
        ss.clear();
        for(int i = tar; i<=n; i++) {
            tmp=R[i].a;
            while(ss.count(tmp) && tmp >= 2) ss.erase(tmp),tmp--; 
            ss.insert(tmp);
            if(tmp == 1) {tar = 1000000000;break;}
        }
        if(tar != 1000000000) {puts("NO");continue;} 
        puts("YES");
        for(int i = 1; i<=n; i++) printf("%d",ans[i]);
        puts("");
    }
    return 0 ;
}

总结:

两个地方:首先cmp函数又忘写return了。第二刚开始写成了tmp>=1了,其实应该是tmp>=2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值