CSA Round #54 $\ $Voting
CSA Round #54 \(\ \)Voting
题目大意:
原题网址:戳我戳我!
一次歌唱比赛中,一位歌手刚刚结束表演,评委正在打分。
一共有 \(n\) 位评委,他们每人可以打 \(1\) 分或 \(0\) 分,第 \(i\) 位评委希望歌手的得分为 \(v[i]\)。
评委们有特殊的控分技巧,他们会按一个顺序依次评分,
第一个评分的评委会不管三七二十一打 \(0\) 分。
对于接下来的评委,假设前面 \(a\) 位评委评分总和为\(b\), 评委会认为这位歌手期望得分为 \(\frac{b}{a}n\),
如果这个得分低于他所希望的得分,他会打 \(1\) 分,否则他会打 \(0\) 分。
你希望选手的得分为 \(p\)\((0\leq p\leq n)\),为此你可以调换评委们的评分顺序。
你需要输出一个 \(1~n\) 的排列,第 \(i\) 个位置表示第 \(i\) 个评分的裁判的编号,让选手的得分最接近 \(p\)。
如果有多种,你只需要输出任意一种。
思路解法
假设裁判的期望得分是有序的,那么按编号顺序投票得分最大,按编号顺序倒序投票得分最小。
这个非常的显然。证明之类的略。
然后我们可以发现一个至关重要的结论:
如果评分顺序中相邻两位裁判的期望得分为\(a\)和\(b\),
并且\(a\leq b\),那么交换这两位裁判,答案要么不变要么减少\(1\)。
证明如下 , 一共分四种情况,假设原来:
- a=0且b=0 ,交换后,a、b的前面状态未变,仍为0,答案不变。
- a=1且b=0 ,交换后,b为1(比b怂的a在那里都为1),a的状态未知,答案不变或者减一。
- a=0且b=1 ,交换后,b为1 且 a为0,b的前面状态未变,a在前面都是0到后面更不可能为1了,答案不变。
- a=1且b=1 ,交换后,b为1显然,a的状态未知,答案不变或减一。
- 综上所述,若\(a\leq b\),交换\(a\)与\(b\)后,答案不变或者减一。
考虑\(1\ 2\ 3\ 4\ 5\ ...\ n\)如何每次交换一个相邻的顺序对变成\(n\ n-1\ ...\ 2\ 1\) 。
其实与冒泡排序差不多:
\(1\ 2\ 3\ 4\) >>> \(1\ 2\ 4\ 3\) >>> \(1\ 4\ 2\ 3\) >>> \(4\ 1\ 2\ 3\) >>> \(4\ 1\ 3\ 2\ \)>>>\(4\ 3\ 1\ 2\)>>>\(4\ 3\ 2\ 1\)
由我们上面得到的结论可知,总分\(score\)是不断递减的。
设最大得分为\(Max\),最小得分为\(Min\)。
我们可以断定,如果\(p\in [Min,Max]\),那么一定是可以取到的。
所以我们二分上述交换进行了多少次,然后构造出此时的序列,计算出此时的分数继续处理即可。
如果无解,那么最终答案序列为最大或最小值序列中的一个。
实现代码
注:此题代码实现中,变换顺序与上述相反,为\(n\ ...\ 2\ 1\)变到\(1\ 2\ ... \ n\)。
#include<bits/stdc++.h>
#define RG register
#define IL inline
#define ll long long
#define _ 500005
using namespace std;
ll pre[_] , stp[_] , n , p , f[_] , score;
struct Judger { ll v , id ; } q[_] ; ll L , R , l , r; bool flag;
IL bool cmp(RG Judger A,RG Judger B){return A.v > B.v;}
IL int GetBlock(RG ll ps){
l = 0 , r = n-1 ; RG ll res = -1;
while(l <= r){
RG ll mid = (l + r) >> 1;
if(pre[ mid ] <= ps){res = mid; l = mid + 1;}
else r = mid - 1;
}return res;
}
IL ll Calc(){
RG ll res = 0;
for(RG ll i = 2; i <= n; i ++)
if(res * n < (i-1) * q[f[i]].v)res ++;
return res ;
}
IL void Rest(){
for(RG ll i = 1; i <= n; i ++)f[i] = i;
score = Calc();
for(RG ll i = 1; i <= n; i ++)f[i] = n-i+1;
if(abs(p - score) < abs(p - Calc()))
for(RG ll i = 1; i <= n; i ++)f[i] = i;
return;
}
IL void Build(RG ll mid){
RG ll blk = GetBlock(mid),rest,t;
for(RG ll i = 1; i <= blk; i ++)f[i] = i;
rest = mid - pre[blk]; ++ blk;
t = blk + 1;
for(RG ll i = n; i >= n-rest+1; i --)f[i] = t ++;
f[n - rest] = blk;
for(RG ll i = n-rest-1; i >= blk; i --)f[i] = t ++;
}
int main(){
cin >> n >> p;
for(RG ll i = 1; i <= n; i ++)
cin >> q[i].v , q[i].id = i;
sort(q + 1,q + n + 1,cmp);
for(RG ll i = 1; i <= n; i ++)stp[i] = n - i;
for(RG ll i = 1; i <= n; i ++)pre[i] = pre[i-1] + stp[i];
flag = false;
L = 0; R = n * (n-1) / 2;
while( L <= R ){
RG ll mid = (L + R) >> 1;
Build(mid);
score = Calc();
if(score == p){flag = true; break;}
else if(score < p)R = mid - 1;
else L = mid + 1;
}
if(!flag)Rest();
for(RG ll i = 1; i <= n; i ++)printf("%lld ",q[f[i]].id);
return 0;
}
随机推荐
- LeetCode - 728. Self Dividing Numbers
A self-dividing number is a number that is divisible by every digit it contains. For example, 128 is ...
- C++函数返回值发生的对象复制
最近用QT做一个监控系统的项目,需要显示目标的运动轨迹,每次目标移动后,就在目标的轨迹中(用vector记录)添加一条新轨迹. 但是在运行中画面里一直不出现轨迹,经过调试发现是记录轨迹的函数出错了. ...
- 阿里云学习之IOT物联网套件(配置篇)
文档时间:2018.-1-24 首注:此文章是参照以下文章的整合与补充: https://bbs.aliyun.com/read/309106.html?amp;displayMode=1&p ...
- 洛谷P2286 [HNOI2004]宠物收养场【Treap】题解+AC代码
题目传送门啦~啦~啦~ 题目描述 凡凡开了一间宠物收养场.收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物. 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的 ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- 删除apache注册表
将Apache服务从系统服务中移除: 其实很多服务我们卸载软件后还会残留在服务列表里面,今天给大家提供个删除残留服务的方法注册表清除法. 1.在我的电脑上右键管理,找到看看那些服务是你不需要的,或是残 ...
- django-高级视图和url配置
高级视图和url配置 一.URLconf技巧 1.流线型化函数导入 对于配置url,我们可以使用以下几种方式: (1)引入view中的函数 from firstSite.view import cur ...
- ios设备触发虚拟键盘输入后position:fixed 无效的一些简单另类的解决方法。
首先看一下我要解决的问题,第一张图是正常的情况下,第二张图是点击了输入框之后的情况,就是要解决此问题~! 百度了一下解决方法,好像有以下的一些方法: 1. iscroll 2. Jquery Mobi ...
- 《android开发进阶从小工到专家》读书笔记--HTTP网络请求
No1: 客户端与服务器的交互流程: 1)客户端执行网络请求,从URL中解析出服务器的主机名 2)将服务器的主机名转换成服务器的IP地址 3)将端口号从URL中解析出来 4)建立一条从客户端与Web服 ...
- poj 3278 简单BFS
题意:给定农夫和奶牛的初始位置,农夫可以当前位置+1.-1.*2三种移动方式,问最少需要多少分钟抓住奶牛 AC代码: #include<cstdio> #include<cstrin ...