BZOJ 1071 组队 详解(单调队列)
来源:互联网 发布:一个简单的python程序 编辑:程序博客网 时间:2024/05/22 10:58
1071: [SCOI2007]组队
Time Limit: 3 Sec Memory Limit: 128 MB
Description
NBA每年都有球员选秀环节。通常用速度和身高两项数据来衡量一个篮球运动员的基本素质。假如一支球队里
速度最慢的球员速度为minV,身高最矮的球员高度为minH,那么这支球队的所有队员都应该满足: A * ( height
– minH ) + B * ( speed – minV ) <= C 其中A和B,C为给定的经验值。这个式子很容易理解,如果一个球队的
球员速度和身高差距太大,会造成配合的不协调。 请问作为球队管理层的你,在N名选秀球员中,最多能有多少名
符合条件的候选球员。
Input
第一行四个数N、A、B、C 下接N行每行两个数描述一个球员的height和speed
Output
最多候选球员数目。
Sample Input
4 1 2 10
5 1
3 2
2 3
2 1
Sample Output
4
HINT
数据范围: N <= 5000 ,height和speed不大于10000。A、B、C在长整型以内。
思路:
一看,这不是n^3吗?再仔细想想,还是n^3呀!
绝望。。n^2log好像也过不了诶(还是有大佬卡过),n^2是正解??枚举minH,minS不就n^2了吗?难道是指针扫一遍,听着像那么回事。额,但是写不来。。%大佬
弄两个数组保存信息,同时处理每个运动员val=A * h+B * s,sh数组按h排序,sv数组按val排序。
外层在sh中枚举i(minS),内层在sh数组里升序枚举j(minH),拿l,r两个指针在sh和sv里面扫。用r扫sv数组添加球员,用l扫sh数组删减球员。
移项可知sv[r].val<=A * minH+B * minS+C时sv[r]才可能被选中
这时sv[r]还要保证s>minS,同时我们不能让v过大导致h比之前的minH小(本来就是非法状态,也保证不到l指针处理过的区间里去),所以把h从式子里去掉再移项得s<=minS+C/B。
然后用l扫sh数组删除不合法的球员,如果一个球员的h比minH小并且满足上边s的判定条件,那么就把它删掉>
为什么不在扫r指针时用h>=minH判h是否合法呢?因为在内层枚举时minH在增加,可能它对于当前的minH合法了,但是之后又不合法了。
还有一些细节和原因请参照代码注释。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define LL long long using namespace std; const int N = 5010; int n,ans; LL A, B, C; struct ER{ int h, s; LL val; }sh[N], sv[N]; inline bool cmph(ER aa, ER bb){ return aa.h < bb.h; } inline bool cmpv(ER aa, ER bb){ return aa.val < bb.val; } int main(){ cin >> n >> A >> B >> C; for(int i=1; i<=n; i++){ scanf("%d%d", &sh[i].h, &sh[i].s); sh[i].val = A * sh[i].h + B * sh[i].s; sv[i] = sh[i]; } sort(sh+1, sh+n+1, cmph); sort(sv+1, sv+n+1, cmpv); int l, r, cnt; for(int i=1; i<=n; i++){//枚举i为speed最小的球员 l = r = 0; cnt = 0; LL mx = sh[i].s + C / B;//超过mx,h就一定小于 sh[j].h了 for(int j=1; j<=n; j++){//枚举j为height最小的球员 while(r<n && sv[r+1].val<=A*sh[j].h+B*sh[i].s+C){//满足条件A*(height-minH)+B*(speed-minV)<=C r++;//A*sh[j].h+B*sh[i].s+C是递增的,所以对于每一个i,r都是单调的 if(sv[r].s>=sh[i].s && sv[r].s<=mx) cnt++; //因为sv[r+1].val>A*sh[j-1].h+B*sh[i].s+C(终止while的条件) //所以只要我们保证 sv[r+1].s<=mx 那么 sv[r+1].h 就一定大于sh[j-1].h //这样的话这个球员才会在一会删除的时候考虑到 }//统计了不考虑h的合法球员。 while(l<n && sh[l+1].h<sh[j].h){ l++;//sh[j].h是递增的,所以对于每一个i,l都是单调的 if(sh[l].s>=sh[i].s && sh[l].s<=mx/* && sh[l].val<=A*sh[j].h+B*sh[i].s+C*/) cnt--; }//sh[l].s<=mx && sh[l].h<sh[j].h 所以A*sh[l].h+B*sh[i].s < A*sh[j].h+B*sh[i].s+C //一定满足sh[l].val<=A*sh[j].h+B*sh[i].s+C,也就是说一定是加入过的(不重不漏) ans = max(ans, cnt); } } printf("%d\n", ans); return 0;}
- BZOJ 1071 组队 详解(单调队列)
- [单调队列] BZOJ 1071 [SCOI2007]组队
- [BZOJ]1071: [SCOI2007]组队 STL优先队列
- bzoj 1047(单调队列)
- bzoj 2276: [Poi2011]Temperature(单调队列)
- 【bzoj 2276】[Poi2011]Temperature(单调队列)
- bzoj 1293: [SCOI2009]生日礼物 (单调队列)
- bzoj 1293单调队列(vector实现)
- Luogu 2827/bzoj 4721(单调队列)
- BZOJ 1047 单调队列
- BZOJ 4385 单调队列
- BZOJ 2096 单调队列
- bzoj 2227 单调队列
- bzoj 1047 单调队列
- BZOJ 1342 单调队列
- dp单调队列(详解)
- BZOJ 1012 单调队列+二分
- BZOJ 2096: pilots 单调队列
- c++ 拆分字符串
- div获取焦点
- window.showModalDialog弹出悬浮框
- 【ORACLE】安装时遇到“display at least 256 colors”
- 安装Maven插件
- BZOJ 1071 组队 详解(单调队列)
- Capture Options(捕获选项)各项的含义与设定
- PHP内写css样式
- HDOJ HDU 1099 Lottery
- Android studio 编辑build.gradle文件时非常卡?
- Lua和C++交互
- PostGIS空间数据库SRID背景知识
- 笨办法20函数和文件
- 修改Xib文件不起作用 ( xCode缓存DerivedData目录 )