http://codeforces.com/contest/732/problem/E

题目说得很清楚,每个电脑去插一个插座,然后要刚好的,电脑的power和sockets的值相同才行。

如果不同,还有一个操作,就是在sockets中插东西,使得sockets的值变成val / 2 + (val & 1)

要求输出最多插多少个电脑和最小的代价。

开始的时候,就有一个暴力的思路了,

就是,用优先队列维护sockets,每次弹出插了最小adapters的一个sockets,然后就是电脑那里找,有得插就插。

找的时候,明显可以把电脑的val排序,然后二分加速。但是有一个问题,就是电脑的val可能是相同的。然后查找完后,

又要标记它用了,后来二分的时候就很麻烦,如果删除,复杂度也高。

同时因为也要记录电脑的id(因为要输出方案),这样用set来保存的话,我刚开始不懂set.lower_bound中怎么二分其中一个值,

因为我只需要二分val。其实就把整个结构体二分就行了,会根据你的重载运算符来二分的,优先二分val,再二分id。

而且set的删除也可以Logn,所以这题就相当于是STL的题了。

set删除迭代器,处理下边界就好,it == ss.end()的时候、

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
struct nodeComputer {
int val, id;
bool operator < (const struct nodeComputer &rhs) const {
if (val != rhs.val) return val < rhs.val;
else return id < rhs.id;
}
nodeComputer(int a, int b) : val(a), id(b) {}
};
struct nodeSocket {
int val, id, cnt;
bool operator < (const struct nodeSocket &rhs) const {
if (cnt != rhs.cnt) return cnt > rhs.cnt;
else if (val != rhs.val) return val > rhs.val;
else return id > rhs.id;
}
nodeSocket(int a, int b, int c) : val(a), id(b), cnt(c) {}
};
set<struct nodeComputer>ss;
priority_queue<struct nodeSocket>que;
int ansSocker[maxn];
int ansComputer[maxn];
void work() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) {
int val;
scanf("%d", &val);
ss.insert(nodeComputer(val, i));
}
// for (set<struct nodeComputer> :: iterator it = ss.begin(); it != ss.end(); ++it) {
// printf("%d %d\n", it->val, it->id);
// }
// set<struct nodeComputer> :: iterator it = ss.lower_bound(nodeComputer(1, 3));
// printf("%d\n", it == ss.end());
for (int i = ; i <= m; ++i) {
int val;
scanf("%d", &val);
que.push(nodeSocket(val, i, ));
}
int ansc = , ansu = ;
while (!que.empty()) {
struct nodeSocket t = que.top();
que.pop();
set<struct nodeComputer> :: iterator it = ss.lower_bound(nodeComputer(t.val, ));
if (it == ss.end() || it->val != t.val) {
if (t.val == ) continue; //再分解就没意思了
que.push(nodeSocket(t.val / + (t.val & ), t.id, t.cnt + ));
} else if (it->val == t.val) {
ansSocker[t.id] = t.cnt;
ansComputer[it->id] = t.id;
ansc++;
ansu += t.cnt;
ss.erase(it);
}
}
printf("%d %d\n", ansc, ansu);
for (int i = ; i <= m; ++i) {
printf("%d ", ansSocker[i]);
}
printf("\n");
for (int i = ; i <= n; ++i) {
printf("%d ", ansComputer[i]);
}
printf("\n");
} int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
work();
return ;
}

然而因为没个插头都会判断是否要用,该是要插多少个adapters的,还是要插。用一个普通队列来维护,能达到一样的效果。

时间就降下来了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
struct nodeComputer {
int val, id;
bool operator < (const struct nodeComputer &rhs) const {
if (val != rhs.val) return val < rhs.val;
else return id < rhs.id;
}
nodeComputer(int a, int b) : val(a), id(b) {}
};
struct nodeSocket {
int val, id, cnt;
bool operator < (const struct nodeSocket &rhs) const {
if (cnt != rhs.cnt) return cnt > rhs.cnt;
else if (val != rhs.val) return val > rhs.val;
else return id > rhs.id;
}
nodeSocket(int a, int b, int c) : val(a), id(b), cnt(c) {}
};
set<struct nodeComputer>ss;
queue<struct nodeSocket>que;
int ansSocker[maxn];
int ansComputer[maxn];
void work() {
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; ++i) {
int val;
scanf("%d", &val);
ss.insert(nodeComputer(val, i));
}
// for (set<struct nodeComputer> :: iterator it = ss.begin(); it != ss.end(); ++it) {
// printf("%d %d\n", it->val, it->id);
// }
// set<struct nodeComputer> :: iterator it = ss.lower_bound(nodeComputer(1, 3));
// printf("%d\n", it == ss.end());
for (int i = ; i <= m; ++i) {
int val;
scanf("%d", &val);
que.push(nodeSocket(val, i, ));
}
int ansc = , ansu = ;
while (!que.empty()) {
struct nodeSocket t = que.front();
que.pop();
set<struct nodeComputer> :: iterator it = ss.lower_bound(nodeComputer(t.val, ));
if (it == ss.end() || it->val != t.val) {
if (t.val == ) continue; //再分解就没意思了
que.push(nodeSocket(t.val / + (t.val & ), t.id, t.cnt + ));
} else if (it->val == t.val) {
ansSocker[t.id] = t.cnt;
ansComputer[it->id] = t.id;
ansc++;
ansu += t.cnt;
ss.erase(it);
}
}
printf("%d %d\n", ansc, ansu);
for (int i = ; i <= m; ++i) {
printf("%d ", ansSocker[i]);
}
printf("\n");
for (int i = ; i <= n; ++i) {
printf("%d ", ansComputer[i]);
}
printf("\n");
} int main() {
#ifdef local
freopen("data.txt","r",stdin);
#endif
work();
return ;
}

Codeforces Round #377 (Div. 2) E. Sockets的更多相关文章

  1. Codeforces Round #377 (Div. 2) D. Exams

    Codeforces Round #377 (Div. 2) D. Exams    题意:给你n个考试科目编号1~n以及他们所需要的复习时间ai;(复习时间不一定要连续的,可以分开,只要复习够ai天 ...

  2. Codeforces Round #377 (Div. 2)

    #include <iostream> #include <stdio.h> #include <string.h> using namespace std; in ...

  3. Codeforces Round #377 (Div. 2)D(二分)

    题目链接:http://codeforces.com/contest/732/problem/D 题意: 在m天中要考k个课程, 数组a中有m个元素,表示第a[i]表示第i天可以进行哪门考试,若a[i ...

  4. Codeforces Round #377 (Div. 2) D. Exams 贪心 + 简单模拟

    http://codeforces.com/contest/732/problem/D 这题我发现很多人用二分答案,但是是不用的. 我们统计一个数值all表示要准备考试的所有日子和.+m(这些时间用来 ...

  5. Codeforces Round #377 (Div. 2) 被坑了

    http://codeforces.com/contest/732/problem/B 题目要求任意两个连续的日子都要 >= k 那么如果a[1] + a[2] < k,就要把a[2]加上 ...

  6. Codeforces Round #377 (Div. 2)A,B,C,D【二分】

    PS:这一场真的是上分场,只要手速快就行.然而在自己做的时候不用翻译软件,看题非常吃力非常慢,还有给队友讲D题如何判断的时候又犯了一个毛病,一定要心平气和,比赛也要保证,不要用翻译软件做题: Code ...

  7. Codeforces Round #377 (Div. 2) B. Cormen — The Best Friend Of a Man(贪心)

     传送门 Description Recently a dog was bought for Polycarp. The dog's name is Cormen. Now Polycarp has ...

  8. Codeforces Round #377 (Div. 2) D. Exams(二分答案)

    D. Exams Problem Description: Vasiliy has an exam period which will continue for n days. He has to p ...

  9. Codeforces Round #377 (Div. 2) C. Sanatorium 水题

    C. Sanatorium time limit per test 1 second memory limit per test 256 megabytes input standard input ...

随机推荐

  1. 团队作业第5周——测试与发布(Alpha版本)

    1.发现的bug a.同时按下和蛇前进方向相反的键和垂直方向的任意一个键贪吃蛇会死亡(比如贪吃蛇向右行走,同时按左上或左下都会game over) b.刷新的苹果会在蛇身上出现 暂时还没能力修复,以后 ...

  2. next enum in swift

    enum Iter: Int{ case s1=0, s2, s3, s4 mutating func next(){ if self == .s4 { self = .s1 return } sel ...

  3. 注意!!一定要谨慎使用c/c++原生指针

    使用指针,要非常小心,今天在做一个小游戏时,就碰到一个使用原生指针的问题,找了好几个小时,才定位到问题的所在,晕. 主要是顶层逻辑中引用了一个指针,而在业务逻辑中将此指针删除了.这种在代码量很少的情况 ...

  4. BZOJ_3550_[ONTAK2010]Vacation&&BZOJ_1283:_序列_网络流解线性规划

    BZOJ_3550_[ONTAK2010]Vacation&&BZOJ_1283:_序列_网络流解线性规划 Description 给出一个长度为 的正整数序列Ci,求一个子序列,使得 ...

  5. WC2017 冬眠记

    2017年2月3日,为期7天的冬眠营冬令营正式开幕. 前4天我们见到了各种集训队dalao们的华丽身姿 感受到了听课听不懂睡觉又惭愧的无力感 见到了几百号人近一半玩手机,剩下的一半有一半在睡觉,再剩下 ...

  6. Redux API之Store

    Store Store 就是用来维持应用所有的 state 树 的一个对象. 改变 store 内 state 的惟一途径是对它 dispatch 一个action. Store 不是类.它只是有几个 ...

  7. windows64位 redis安装 步骤

    官方下载:http://redis.io/download 可以根据需要下载不同版本 windows版:https://github.com/MSOpenTech/redis/releases 在D盘 ...

  8. Ext.Net 复制GridPanel的数据

    Ext.Net 复制GridPanel的数据 2013-11-28 09:50:04|  分类: Ext.net |  标签: |举报 |字号大中小 订阅     CSS: <styletype ...

  9. Android下如何计算要显示的字符串所占的宽度和高度

    Rect bounds = new Rect(); String text = "Hello World"; TextPaint paint; paint = findViewBy ...

  10. 【转】 mybatis如何在控制台打印执行的sql语句

    <strong>######################################################################### #Root Logger ...