QZOI2019 CSP-S模拟赛 T1

错误的贪心导致考场上只有10pts... 看来以后贪心还是需要先证明啊

题目描述

小A和小B在玩一个游戏,他们两个人每人有 $n$ 张牌,每张牌有一个点数,并且在接下来的 $n$ 个回合中每回合他们两人会分别打出手中的一张牌,点数严格更高的一方得一分,然而现在小A通过某种神秘的方法得到了小B的出牌顺序,现在他希望规划自己的出牌顺序使得自己在得分尽可能高的前提下出牌的字典序尽可能大。

题意分析

给出一个数列$b$,给出一个相同长度的数列$a$,要求重新排列$a$,使得最多的$a_i>b_i$,输出字典序最大的一种方案。

思路分析

很自然地想到贪心。

考场上:字典序最大,那倒着最小不就得了(草我是什么sb),10pts

为什么是错的?实际上,如果在线输入在线构造数列$a$,有很多种情况会导致错误。

可以发现,得分与数列的顺序是没有关系的。因此我们完全可以先构造出最大得分,再来构造最大字典序。

具体实现

怎么构造最大得分?可以将$a$和$b$都排序,然后降序遍历$b$,对于当前的$b$,如果当前的$a_i$能得分,就得一分;否则继续遍历。

然后我们构造出一个得分方案。设想,构造出一个得分方案后,我们为了保证得分不变,不能再动已经定下来的这些牌;但我们可以用更大的牌来代替其中的一些牌,这样得分不变。因此我们先构造出一个最小的方案,这样剩下的大牌可以放到不得分的地方,也可以来替代得分的地方,可能性才多。当然,对于构造出的这个方案,我们也要使它在不改变牌组成的情况下,字典序最大。我们暂且将这些没有得分的大牌称为活动牌。

然后我们就开始从前往后遍历$b$序列,若当前元素处于得分方案内,看看有没有活动牌可以替代它,如果有,就用这张牌替代它,并让原来的方案牌成为活动牌;若当前元素不处于得分方案内,我们也可以从方案牌中拿一张最大的牌,当然,如果要拿牌,这张牌一定要可以得分,否则会导致得分减少,同时,因为这里会从方案牌中拿牌,处理得分方案内的牌时,要注意判断当前分配到的方案牌有没有提前被取走。

以上的算法可以通过multiset实现,部分步骤也可以用大根堆替代以降低复杂度,但比较复杂。

下面给出本文代码中用到的一些multiset操作的解释:(可以参考蓝书或网上资料)

multiset<int> s:定义一个有序可重集s
multiset<int>::iterator it:定义一个迭代器it,可以用“*”取消引用
s.insert(x):向s中插入数x
s.erase(it):从s中删除迭代器it指向的元素
s.find(x):返回s中指向x的迭代器
s.begin():返回s中指向第一个元素的迭代器
s.end():返回s中指向最后一个元素后一个地址的迭代器
s.rbegin():返回s中指向最后一个元素的反向迭代器,反向的意思是,若执行++操作,则会向s的前一位移动

考场上忘记函数怎么写怎么办?打开Dev-Cpp目录,搜索头文件set,找到对应的函数即可

//贪心
//先保证得分最大,再保证字典序最大。可以先处理出最大得分的一种方案,然后再调整字典序到最大
//其它有的贪心算法可能会导致字典序或者得分顾此失彼,是错误的
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
#define id(i) w[i].id
#define v(i) w[i].v
using namespace std;
const int N=1e5+100;
struct B
{
int id,v;
}w[N];
int n,cnt;
int b[N],ans[N];
multiset<int> s1,s2;
multiset<int>:: iterator it;
bool cmp(B x,B y)
{
return x.v<y.v;
}
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]),v(i)=b[i],id(i)=i;
for(int i=1,x;i<=n;i++)
scanf("%d",&x),s1.insert(x),s2.insert(x);
sort(w+1,w+n+1,cmp);
for(int i=n;i;i--)
if(*s2.rbegin()>v(i))
cnt++,s2.erase(s2.find(*s2.rbegin()));//计算最大得分
//先构造出一种出牌最小的方案,这样剩下的活动的牌就大,构造大字典序的空间就大
//本步过后,s1存储的就是方案外的活动牌
//活动牌的定义是,不可以得分的,可以随意移动的牌
for(int i=1;i<=cnt;i++)
{
it=s1.upper_bound(v(i));
ans[id(i)]=*it;s1.erase(s1.find(*it));
}
s2.clear();
for(int i=1;i<=n;i++)
if(ans[i])
s2.insert(ans[i]);//s2存储已构造出的一种方案
for(int i=n;i;i--)
if(ans[i])
{
it=s2.upper_bound(b[i]);
ans[i]=*it,s2.erase(it);
}//将s2的字典序弄到最大
for(int i=1;i<=n;i++)
if(ans[i])
s2.insert(ans[i]);//再存回去
//不改变原方案的牌,为了使字典序最大,可以在活动牌和本来分配给它的牌中找最大的
for(int i=1;i<=n;i++)
if(ans[i] && s2.find(ans[i])!=s2.end())//原方案已分配的部分
s1.insert(ans[i]),s2.erase(s2.find(ans[i])),printf("%d ",*s1.rbegin()),s1.erase(s1.find(*s1.rbegin()));
else//没被分配到的部分
{
if(s2.size() &&(*s1.rbegin()>b[i] || *s2.rbegin()>b[i]))//可以在s2中取个最大的拉过去得分
s1.insert(*s2.rbegin()),s2.erase(s2.find(*s2.rbegin()));
printf("%d ",*s1.rbegin()),s1.erase(s1.find(*s1.rbegin()));
}
return 0;
}

[QZOI2019]Game 题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

随机推荐

  1. PHP debug_zval_dump() 函数

    debug_zval_dump 函数用于查看一个变量在zend引擎中的引用计数.类型信息. 版本要求:PHP 4 >= 4.2.0, PHP 5, PHP 7高佣联盟 www.cgewang.c ...

  2. PHP xml_parser_create() 函数

    定义和用法 xml_parser_create() 函数创建 XML 解析器.高佣联盟 www.cgewang.com 如果成功,该函数则返回可被其它 XML 函数使用的资源句柄.如果失败,则返回 F ...

  3. 4.9 省选模拟赛 圆圈游戏 树形dp set优化建图

    由于圆不存在相交的关系 所以包容关系形成了树的形态 其实是一个森林 不过加一个0点 就变成了树. 考虑对于每个圆都求出最近的包容它的点 即他的父亲.然后树形dp即可.暴力建图n^2. const in ...

  4. bzoj 4305 数列的GCD

    LINK:数列的GCD 题意: 给出一个长度为N的数列{a[n]},1<=a[i]<=M(1<=i<=N). 现在问题是,对于1到M的每个整数d,有多少个不同的数列b[1], ...

  5. Java对象(创建过程、内存布局、访问方法)

    (Java 普通对象.不包括数组.Class 对象等.) ​ 对象创建过程 类加载 遇到 new 指令时,获取对应的符号引用,并检查该符号引用代表的类是否已被初始化.如果没有就进行类加载. 分配内存 ...

  6. Linux的VMWare下Centos7的三种网络配置过程(网络二)

    Linux之VMWare下Centos7的三种网络配置过程 环境:虚拟软件:VMWare 14.0客户机:windows 10虚拟机:centos 7 VMware三种网络连接方式 Bridge(桥接 ...

  7. [转]Maven类包冲突终极三大解决技巧

    举例 A依赖于B及C,而B又依赖于X.Y,而C依赖于X.M,则A除引B及C的依赖包下,还会引入X,Y,M的依赖包(一般情况下了,Maven可通过<scope>等若干种方式控制传递依赖).这 ...

  8. 一文入门人工智能的明珠:生成对抗网络(GAN)

    一.简介 在人工智能领域内,GAN是目前最为潮流的技术之一,GAN能够让人工智能具备和人类一样的想象能力.只需要给定计算机一定的数据,它就可以自动联想出相似的数据.我们学习和使用GAN的原因如下: 1 ...

  9. JS中的数组复制问题

    JS中的数组复制问题 前言 首先提到复制,也就是拷贝问题,就必须要明确浅拷贝和深拷贝. 浅拷贝:B由A复制而来,改变B的内容,A也改变 深拷贝:B由A复制而来,改变B的内容,A的内容不会改变 总的来说 ...

  10. aria2使用ajax调用/页面浏览器RPC调用aria2

    @ 目录 1. aria2使用ajax调用/页面浏览器RPC调用aria2 1.1. 总结: 1.2. ajax调用aria2-Demo 1.3. postMan命令测试 1.3.1. post基本使 ...