原文链接https://www.cnblogs.com/zhouzhendong/p/9255885.html

题目传送门 - CF873E

题意

  现在要给 $n(n\leq 3000)$ 个学生颁奖。

  记 $a_i$ 为第 $i$ 个学生在本次比赛中做出的题目数量。

  记 $b_i$ 为第 $i$ 个学生所获的奖项,其中 $1,2,3$ 分别表示他获得一、二、三等奖, $-1$ 表示不获奖,当然,一等奖最好,没奖最差。

  记 $cnt_i$ 为满足 $b_k=i$ 的 $k$ 的个数。

  一个合法的颁奖方案必须满足以下条件:

    对于任何的 $i,x,y\in {1,2,3}$,

      1.  $cnt_i>0$

      2.  $cnt_x\leq 2cnt_y$

    如果第 $i$ 个人比第 $j$ 个人做题数多,则第 $i$ 个人获得的奖不比第 $j$ 个人差。

  现在,记 $b_i=j$ 的 $i$ 中,使得 $a_i$ 最大的记为 $c_j$ , 使得 $a_i$ 最小的记为 $d_j$。

  请你在所有合法方案中选择 $d_1-c_2$ 最大的;如果有多个,再在其中选择 $d_2-c_3$ 最大的;如果有多个,再在其中选择 $d_3-c_{-1}$ 最大的;如果还有多个,那么选择任意方案。

  按照输入的人的顺序输出你选择的方案中各个人的奖项。

题解

  VP 的时候想了个很真的假算法,好久以后才发现的。

  正确的做法:

  首先将所有人按照 $a$ 降序排列。

  枚举 $d_1$ 的位置 $i$

    枚举 $d_2$ 的位置 $i+j$

      在满足 $i\leq 2j,j\leq 2i$ 的情况下,继续下面的操作:

      令 $d3=i+j+k$ ,则 $k$ 需要满足:对于任何的 $i,x,y\in {1,2,3}$,1.$cnt_i>0$ 2.$cnt_x\leq 2cnt_y$。

      那么,$k$ 的取值范围是 $\left[\max(\left\lfloor\cfrac{i+1}2\right\rfloor,\left\lfloor\cfrac{j+1}2\right\rfloor,\min(2i,2j,n)\right]$ ,于是我们需要找到一个 $k$ 满足 $a_k-a_{k+1}$ 最大。

      由于没有修改,我们可以用 ST表 预处理,$O(1)$ 实现询问。于是我们就可以得到要选择的 $k$ 了。每次通过新的 $i,j,k$ 生成新的 $d_1,d_2,d_3$ 与目前最优解择优录用。

  最终根据最优解定奖,别忘了最后要排序一遍把所有的人排回输入顺序。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=3005;
int n,ST[N][14];
struct pb{
int a,id,res;
}a[N];
bool cmpa(pb a,pb b){
return a.a>b.a;
}
bool cmpid(pb a,pb b){
return a.id<b.id;
}
int calc(int i){
return a[i].a-a[i+1].a;
}
int Query(int L,int R){
if (L>R)
return -1;
int d=log(R-L+1)/log(2.0);
int a=ST[L+(1<<d)-1][d],b=ST[R][d];
return calc(a)>calc(b)?a:b;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]),a[i].id=i;
sort(a+1,a+n+1,cmpa);
a[n+1].a=0;
for (int i=1;i<=n;i++){
ST[i][0]=i;
for (int j=1;j<=12;j++){
ST[i][j]=ST[i][j-1];
if (i-(1<<(j-1))>0&&calc(ST[i-(1<<(j-1))][j-1])>calc(ST[i][j]))
ST[i][j]=ST[i-(1<<(j-1))][j-1];
}
}
int d1=-1,d2=-1,d3=-1;
for (int i=1;i<=n;i++)
for (int j=1;i+j<=n;j++){
if (i>2*j||j>2*i)
continue;
int dd1=i,dd2=i+j,dd3=Query(dd2+max((i+1)/2,(j+1)/2),min(dd2+min(i*2,j*2),n));
int k=dd3-dd2;
if (dd3==-1||k<1)
continue;
if (d1==-1||calc(dd1)>calc(d1)||(calc(dd1)==calc(d1)&&(calc(dd2)>calc(d2)||(calc(dd2)==calc(d2)&&calc(dd3)>calc(d3)))))
d1=dd1,d2=dd2,d3=dd3;
}
for (int i=1;i<=d1;i++)
a[i].res=1;
for (int i=d1+1;i<=d2;i++)
a[i].res=2;
for (int i=d2+1;i<=d3;i++)
a[i].res=3;
for (int i=d3+1;i<=n;i++)
a[i].res=-1;
sort(a+1,a+n+1,cmpid);
for (int i=1;i<=n;i++)
printf("%d ",a[i].res);
return 0;
}

  

Codeforces 873E Awards For Contestants ST表的更多相关文章

  1. Codeforces 475D 题解(二分查找+ST表)

    题面: 传送门:http://codeforces.com/problemset/problem/475/D Given a sequence of integers a1, -, an and q ...

  2. Codeforces 803G Periodic RMQ Problem ST表+动态开节点线段树

    思路: (我也不知道这是不是正解) ST表预处理出来原数列的两点之间的min 再搞一个动态开节点线段树 节点记录ans 和标记 lazy=-1 当前节点的ans可用  lazy=0 没被覆盖过 els ...

  3. ST表入门学习poj3264 hdu5443 hdu5289 codeforces round #361 div2D

    ST算法介绍:[转自http://blog.csdn.net/insistgogo/article/details/9929103] 作用:ST算法是用来求解给定区间RMQ的最值,本文以最小值为例 方 ...

  4. Codeforces Round #422 (Div. 2)E. Liar sa+st表+dp

    题意:给你两个串s,p,问你把s分开顺序不变,能不能用最多k段合成p. 题解:dp[i][j]表示s到了前i项,用了j段的最多能合成p的前缀是哪里,那么转移就是两种,\(dp[i+1][j]=dp[i ...

  5. 【CodeForces】713 D. Animals and Puzzle 动态规划+二维ST表

    [题目]D. Animals and Puzzle [题意]给定n*m的01矩阵,Q次询问某个子矩阵内的最大正方形全1子矩阵边长.n,m<=1000,Q<=10^6. [算法]动态规划DP ...

  6. Codeforces Round #278 (Div. 1) B - Strip dp+st表+单调队列

    B - Strip 思路:简单dp,用st表+单调队列维护一下. #include<bits/stdc++.h> #define LL long long #define fi first ...

  7. Codeforces 359D Pair of Numbers | 二分+ST表+gcd

    题面: 给一个序列,求最长的合法区间,合法被定义为这个序列的gcd=区间最小值 输出最长合法区间个数,r-l长度 接下来输出每个合法区间的左端点 题解: 由于区间gcd满足单调性,所以我们可以二分区间 ...

  8. 【Codeforces Round #466】E. Cashback DP+ST表

    题意 给定$n$个数,将其划分成若干个连续的子序列,求最小价值,数组价值定义为,数组和减去$\lfloor \frac{k}{c} \rfloor$,$k$为数组长度,$c$为给定数 可以列得朴素方程 ...

  9. Codeforces 713D Animals and Puzzle(二维ST表+二分答案)

    题目链接 Animals and Puzzle 题意  给出一个1e3 * 1e3的01矩阵,给出t个询问,每个询问形如x1,y1,x2,y2 你需要回答在以$(x1, y1)$为左上角,$(x1, ...

随机推荐

  1. C/C++ 获取文件大小

    在C语言中测试文件的大小,主要使用二个标准函数. 1.fseek 函数原型:int fseek ( FILE * stream, long int offset, int origin ); 参数说明 ...

  2. Day8--------------yum软件包管理

    1.url三段式:协议.域名.路径 例如:http://wan.360.cn/game 2.本地yum配置: vim /etc/yum.repos.d/local.repo [local] #固定格式 ...

  3. Codeforces 280D k-Maximum Subsequence Sum [模拟费用流,线段树]

    洛谷 Codeforces bzoj1,bzoj2 这可真是一道n倍经验题呢-- 思路 我首先想到了DP,然后矩阵,然后线段树,然后T飞-- 搜了题解之后发现是模拟费用流. 直接维护选k个子段时的最优 ...

  4. 分享一份非常强势的Android面试题

    马上步入金九银十了,是时候看一些面试题去鹅厂了,接下来我将分享一些面试题,每天总结一点点,希望对大家有所帮助! ListView和RecyclerView区别 参考链接: https://blog.c ...

  5. Struts2中类数据封装的方式

    第一种方式:属性驱动提供对应属性的set方法进行数据的封装.表单的哪些属性需要封装数据,那么在对应的Action类中提供该属性的set方法即可.表单中的数据提交,最终找到Action类中的setXxx ...

  6. Confluence 6 管理协同编辑 - 最大编辑者的限制

    我们限制为最多 12 个用户可以同时对一个页面进行编辑.这个意味着当一个页面已经有 12 个用户正在编辑了,13 个用户是不能进入编辑界面的,直到 12 个用户中有一个用户已经离开了. 系统管理员可以 ...

  7. Android 自动化测试框架

    Android常用的自动化测试工具框架: Monkey,MonkeyRunner,UIAutomator,Robotium,Appium,Monkey Talk...... 但这些工具框架都是什么呢有 ...

  8. ionic3 极光推送

    参考网站:http://www.jianshu.com/p/eb8ab29329d9 遇到的问题是  执行以下命令一直报错 cordova plugin add https://github.com/ ...

  9. mabatis的批量新增sql 初级的 初级的 初级的

    简单描述:做开发的时候,会遇到一次插入好多条记录,怎么做好呢? 解决思路:循环insert啊!  哪凉快那呆着去←!←  这样会增加数据库开销的,当然不能这么干了,要在sql上下功夫.看代码,一下就明 ...

  10. python----常用功能

    sintance和type class Foo(object): pass class Bar(Foo): pass obj = Bar() # isinstance用于判断,对象是否是指定类的实例 ...