您的位置:首页 > 编程语言 > Go语言

Codeforces GoodBye2015 New Year and Three Musketeers Codeforces 611E(贪心)

2016-01-02 12:00 519 查看
这道题在比赛的时候一直在想二分答案+贪心判定,结果一直在WA on pretest10……第二天起来一想,发现是有问题的……因为在判定的时候,我是把每一次操作隔离开来看的,但他要求是同时干某件事,所以不能直接给每个人分配k次出手机会。

比如说,现在的分配情况是:

a——b——c

&——_——&

_——&——&

a、c和b、c各一次,如果用之前的策略的话,就还可以用一次a、b,但是,a、b的可用时间是不一样的,所以这是行不通的。

我们现在考虑,一个时间,一个时间地模拟,那么,我们可以模糊地想象出一个贪心的策略。

贪心部分代码:

我们假设a<b<c
注:work(t)是指干掉≤t的最大的一个。
if(mx <= a)    //当最大的<a那么所有的怪都可以被任何一个musketeers消灭
{
cnt --;
cnt += (n+2)/3;
break;
}
else if(mx <= b)//当a < mx <= b时,a先干掉a能干的,b、c干掉最大的两个。
{
sbt.work(a);
sbt.work(b);
sbt.work(c);
}
else if(mx <= c)//当b < mx <= c 时,若a和b都可以干掉一个,那么就分别干掉一个,如果a和b只能干掉一个或更少,那么就用a+b去干掉能干掉的最大的,显然更优。c干掉最大的。
{
bool flag = true;
int tmp = sbt.Prev(sbt.root, a);
if(tmp != -1)
{
int s1 = tmp;
sbt.erase(sbt.root, tmp);
tmp = sbt.Prev(sbt.root, b);
if(tmp != -1)
{
sbt.erase(sbt.root, tmp);
n -= 2;
sbt.work(c);
}
else
{
sbt.insert(sbt.root, s1);
flag = 0;
}
}
else flag = 0;
if(!flag)
{
int aa = a+b, bb = c;
if(aa > bb) swap(aa, bb);
sbt.work(aa);
sbt.work(bb);
}
}
// 考虑多个人一起打怪
else if(mx <= a + b) // c < mx <= a+b
{
int aa = c, bb = a + b;
sbt.work(aa);
sbt.work(bb);
}
else if(mx <= a + c) // c, a+b < mx <= a + c
{
int aa = b, bb = a + c;
sbt.work(aa);
sbt.work(bb);
}
else if(mx <= c + b) // c, a+b, < a+c < mx <= b + c
{
int aa = a, bb = c + b;
sbt.work(aa);
sbt.work(bb);
}
else
{
sbt.work(a+b+c);
}


代码

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 200005
#define INF 0x3f3f3f3f
int n, m, a, b, c, C[3], sd = 2333, sz;
int t[MAXN];
char ch, f;
inline void GET(int &n) {
n = 0; f = 1;
do {ch = getchar(); if(ch == '-') f = -1;} while(ch > '9' || ch < '0');
while(ch >= '0' && ch <= '9') {n=n*10+ch-'0';ch=getchar();}
n *= f;
}
struct Treap {
struct Node {
int v, s[2], cnt, rnd;
} t[MAXN];
int root;
const inline int Rand() { return sd = sd * sd % 1000007; }
inline void Rot(int &k, bool f) {
int p = t[k].s[f]; t[k].s[f] = t[p].s[f^1];
t[p].s[f^1] = k; k = p;
}
void insert(int &k, int v) {
if(!k) { k = ++ sz; t[k].v = v; t[k].rnd = Rand(); t[k].cnt = 1; return; }
if(t[k].v == v) { ++ t[k].cnt; return; }
bool f = v > t[k].v;
insert(t[k].s[f], v);
if(t[t[k].s[f]].rnd > t[k].rnd) Rot(k, f);
}
void erase(int &k, int v) {
if(!k) return;
if(t[k].v == v) {
if(t[k].cnt > 1) -- t[k].cnt;
else if(t[k].s[0] * t[k].s[1] == 0) k = t[k].s[0] + t[k].s[1];
else {
bool f = t[t[k].s[1]].rnd > t[t[k].s[0]].rnd;
Rot(k, f); erase(k, v);
}
return;
}
bool f = v > t[k].v;
erase(t[k].s[f], v);
}
const int Prev(int k, int v, int p = 200003) {
if(!k) return t[p].v;
else if(t[k].v == v) return v;
else if(t[k].v < v) return Prev(t[k].s[1], v, k);
else return Prev(t[k].s[0], v, p);
}
const bool size() { return root; }
const int Max() {
int tmp = root;
while(t[tmp].s[1]) tmp = t[tmp].s[1];
return t[tmp].v;
}
void work(int val) {
if(!root) return;
int tmp = Prev(root, val);
if(tmp == -1) return;
n --;
erase(root, tmp);
}
} sbt;
int main() {
scanf("%d", &n); sbt.root = 0; sbt.t[200003].v = -1;
scanf("%d%d%d", &a, &b, &c);
if(a > b) swap(a, b);
if(a > c) swap(a, c);
if(b > c) swap(b, c);
for(int i = 1; i <= n; ++ i) {
GET(t[i]);
sbt.insert(sbt.root, t[i]);
}
if(sbt.Max() > a + b + c) { puts("-1"); return 0; }
int cnt = 0;
for(;sbt.size() && n;) {
++ cnt;
C[0] = C[1] = C[2] = 0;
int mx = sbt.Max();
if(mx <= a) {
cnt --;
cnt += (n+2)/3;
break;
}
else if(mx <= b) {
sbt.work(a);
sbt.work(b);
sbt.work(c);
}
else if(mx <= c) {
bool flag = true;
int tmp = sbt.Prev(sbt.root, a);
if(tmp != -1) {
int s1 = tmp;
sbt.erase(sbt.root, tmp);
tmp = sbt.Prev(sbt.root, b);
if(tmp != -1) {
sbt.erase(sbt.root, tmp);
n -= 2;
sbt.work(c);
} else {
sbt.insert(sbt.root, s1);
flag = 0;
}
} else flag = 0;
if(!flag) {
int aa = a+b, bb = c;
if(aa > bb) swap(aa, bb);
sbt.work(aa);
sbt.work(bb);
}
}
else if(mx <= a + b) {
int aa = c, bb = a + b;
sbt.work(aa);
sbt.work(bb);
}
else if(mx <= a + c) {
int aa = b, bb = a + c;
sbt.work(aa);
sbt.work(bb);
}
else if(mx <= c + b) {
int aa = a, bb = c + b;
sbt.work(aa);
sbt.work(bb);
}
else {
sbt.work(a+b+c);
}
}
printf("%d\n", cnt);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: