BZOJ 1071组队

 题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1071

题目很好,居然写了很久,题解找了真多;

主要两种做法:

O(n^2lgn),通过优先堆维护,首先 等式变换:A*height+B*speed-C<=A*minheight+B*minspeed;

增加a[i].val=A*height+B*speed-C:

对a按height排序;

然后枚举i 把a[i].s作为min

 1 /* ***********************************************
 2 Author        :forgot93
 3 Created Time  :2014/12/23 星期二 上午 9:00:41
 4 File Name     :
 5 ************************************************ */
 6
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <stdlib.h>
17 #include <time.h>
18 using namespace std;
19
20 #define N 5555
21 typedef long long ll;
22 priority_queue<ll> q;
23
24 struct node
25 {
26     ll h,s;
27     ll val;
28     bool operator < (const node  &b) const{
29     return h>b.h;
30     }
31 }a[N];
32
33
34 int main()
35 {
36     int n;
37     ll A,B,C;
38     cin>>n>>A>>B>>C;
39     for (int i=1;i<=n;i++){
40     cin>>a[i].h>>a[i].s;
41     a[i].val=A*a[i].h+B*a[i].s-C;
42     }
43     ll ans=1;
44     sort(a+1,a+n+1);
45
46     for (int i=1;i<=n;i++)
47     {
48         ll minh=a[i].h;
49         ll mins=a[i].s;
50         while (!q.empty()) q.pop();
51         q.push(a[i].val);
52         for (int j=1;j<=n;j++)
53         if (j!=i&&a[j].s>=mins)
54         {
55             minh=min(minh,a[j].h);
56             ll tmp=B*mins+A*minh;
57             if (a[i].val>tmp) break;
58             while (!q.empty()&&q.top()>tmp) q.pop();
59             if (a[j].val<=tmp)
60             {
61                 q.push(a[j].val);
62                 ans=max(ans,(ll) q.size());
63             }
64         }
65     }
66     cout<<ans<<endl;
67     return 0;
68 }

speed;

接着暂时minheight=a[i].h;

a[i].h 是从大到小排序的;

接下来维护堆,我们枚举j 对于j!=i且a[j].s>=mins,

同时更新minheight;

然后把val满足的压入堆中;

对q.top()>val q.pop();

因为mins固定,minh是单调递减的所以前面满足的后面也会满足(这里请仔细考虑);

时间是1100ms;

第二种是o(n*n);

时间是848ms;

关键字:单调;

 1 /* ***********************************************
 2 Author        :forgot93
 3 Created Time  :2014/12/23 ÐÇÆÚ¶þ ÏÂÎç 2:46:36
 4 File Name     :c.cpp
 5 ************************************************ */
 6
 7 #include <stdio.h>
 8 #include <string.h>
 9 #include <iostream>
10 #include <algorithm>
11 #include <vector>
12 #include <queue>
13 #include <set>
14 #include <map>
15 #include <string>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <time.h>
19 using namespace std;
20
21 typedef long long ll;
22 #define N 5555
23 struct node
24 {
25    int h,v;
26    ll val;
27 }H[N],V[N],a[N],r[N];
28
29 int cmp1(node x,node y)
30 {
31     if (x.h==y.h) return x.v<y.v;
32     return x.h<y.h;
33 }
34 int cmp2(node x,node y)
35 {
36     if (x.v==y.v) return x.h<y.h;
37     return x.v<y.v;
38 }
39
40 int cmp3(node x,node y)
41 {
42     return x.val<y.val;
43 }
44
45
46 int main()
47 {
48     int n;
49     ll A,B,C;
50     cin>>n>>A>>B>>C;
51     for (int i=0;i<n;i++){
52     cin>>a[i].h>>a[i].v;
53     a[i].val=A*a[i].h+B*a[i].v-C;
54     H[i]=V[i]=a[i];
55     }
56     sort(a,a+n,cmp3);
57     sort(V,V+n,cmp2);
58     sort(H,H+n,cmp1);
59     int ans=0;
60     for (int i=0;i<n;i++)
61     {
62         int minh=H[i].h,p=0,cnt=0,tot=0;
63         for (int j=0;j<n;j++)
64         if (V[j].h>=minh&&V[j].v<=H[i].v)
65             r[tot++]=V[j];
66         for (int j=0;j<tot;j++)
67         {
68             int minv=r[j].v;
69             ll res=A*minh+B*minv;
70             while (p<n&&a[p].val<=res)
71             {
72                 if (a[p].h<minh||a[p].v<minv) cnt++;
73                 p++;
74             }
75             ans=max(p-cnt,ans);
76             if (res>=A*r[j].h+B*r[j].v-C) cnt++;
77             if (p==n) break;
78         }
79     }
80     printf("%d\n",ans);
81     return 0;
82 }

 

首先 按照某些关键字排序。

for i minh=a[i].h;

然后枚举 j 寻找mins,mins<a[i],s;

然后是单调队列;

有这样一个性质:我们枚举指针的时候是按val 从小到大拍好顺序的,我们枚举的mins也是从小到大的,所以:

(这里) 前面的元素一定满足后面的,怎么理解?

枚举的mins2能够满足mins1的所有元素,所以指针p不必归0了。

所以就会O(n^2);

时间: 2024-08-01 20:03:13

BZOJ 1071组队的相关文章

bzoj 1071: [SCOI2007]组队

Description NBA每年都有球员选秀环节.通常用速度和身高两项数据来衡量一个篮球运动员的基本素质.假如一支球队里 速度最慢的球员速度为minV,身高最矮的球员高度为minH,那么这支球队的所有队员都应该满足: A * ( height – minH ) + B * ( speed – minV ) <= C 其中A和B,C为给定的经验值.这个式子很容易理解,如果一个球队的 球员速度和身高差距太大,会造成配合的不协调. 请问作为球队管理层的你,在N名选秀球员中,最多能有多少名 符合条件的

(双指针) bzoj 1071

1071: [SCOI2007]组队 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 1267  Solved: 392[Submit][Status][Discuss] Description NBA每年都有球员选秀环节.通常用速度和身高两项数据来衡量一个篮球运动员的基本素质.假如一支球队里速度最慢的球员速度为minV,身高最矮的球员高度为minH,那么这支球队的所有队员都应该满足: A * ( height – minH ) + B * ( sp

【BZOJ 1977】 [BeiJing2010组队]次小生成树 Tree

1977: [BeiJing2010组队]次小生成树 Tree Time Limit: 10 Sec  Memory Limit: 512 MB Submit: 2313  Solved: 544 [Submit][Status][Discuss] Description 小 C 最近学了很多最小生成树的算法,Prim 算法.Kurskal 算法.消圈算法等等. 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了.小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格

BZOJ 1977 [BeiJing2010组队]次小生成树 Tree

严格次小生成树.一开始没有特批一圈都相等的情况,一直WA,十分难受. 先生成最小生成树,枚举每条非树边,连上它构成一个环,拆掉环上树边中最大的一条(若和该边相等则次大的一条)换上这条. 用倍增维护一条链上的最大边和次大边,倍增跑lca同时找出环上最大边和次大边,看能否更新答案. #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath

BZOJ 1976 BeiJing2010组队 能量魔方 Cube 最小割

题目大意 给出一个N×N×N的矩阵,矩阵上的每一个方块可以涂上两种颜色,相邻的两个方块如果涂上了不同的颜色,就会产生一点能量.现在已知了一些方块的颜色,问最多可以产生多少点能量. 思路 假设所有相邻的方块之间全部都产生能量,且不考虑已经上好色的方块,之后减去不合法的就行了. 一般来说这种相邻的方块之间会产生一些什么的一般都是把所有点染色,一种颜色的与S相连,另一种与T相连.这道题中,左侧的点若是最终属于S集,代表这个点上了P色,否则上了N色:右侧的点若是最终属于T集,代表这个点上了P色,否则上了

怒刷BZOJ记录(二)1038~10xx

我实在是太弱了...不滚粗只能刷BZOJ了...这里来记录每天刷了什么题吧. 2015-8-13: 正式开始! 1030[JSOI2007]文本生成器                       | ac自动机+DP 1042 [HAOI2008]硬币购物                        | 容斥原理+背包 1045 [HAOI2008] 糖果传递                       | 数学+中位数 1047 [HAOI2007]理想的正方形               

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比