1071: [SCOI2007]组队

1071: [SCOI2007]组队

https://lydsy.com/JudgeOnline/problem.php?id=1071

分析:

  dp+单调性。

  A*(hi–minH)+B*(si–minV)<=C

  Ahi+Bsi<=C+A*minH+B*minV

  如果枚举一个minH,和一个minV的话,那么把数组按Ahi+Bsi排序后,这个数组就具有单调性了。

  这里面的人不一定满足si>=minV和hi>=minH。先固定一个minV,然后把所有大于等于minV的取出来。这样满足了第一个限制。然后枚举minH的时候会由于minH的增加而导致小于了minH,可以把所有加入的放进小根堆里,然后不断弹出不合法的。这样复杂度是$n^2logn$在bzoj上过不了的(luogu上开O2可以过)

  考虑枚举的时候先si>=minV,那么就有A*(hi-minH)<=C+B*minV-B*si,因为要hi>=minH,所0<=左式<=右式,所以C+B*minV-B*si>=0,得到si<=C/B+mv,注意这样还没有满足左式>=0的条件,但是目前si应该满足minV<=si<=C/B+minV。

  这样依然没有满足左式>=0的条件。考虑减去这些不合法的。这里只需要按h从i小到大的扫描所有人,如果这个si是合法的,那么减去。

  这样减是否会减到一些没有枚举过的?

  

就是枚举下面的序列的时候,是否枚举到上面的排列的后面去。

是不会的。

下面序列的满足,hi<=minH,si<=C/B+minV,所以A*hi+B*si最大是A*minH+B*minV+C,刚好到第一个序列的位置。

代码:

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18 
19 const int N = 100005;
20 
21 struct Node{
22     int h, v; LL tot;
23 }s[N], mv[N], mh[N];
24 
25 bool cmp1(const Node &A, const Node &B) {
26     return A.tot < B.tot; 
27 }
28 bool cmp2(const Node &A, const Node &B) {
29     return A.h < B.h;
30 }
31 bool cmp3(const Node &A, const Node &B) {
32     return A.v < B.v;
33 }
34 
35 int main() {
36     int n = read(); LL A = read(), B = read(), C = read();
37     for (int i = 1; i <= n; ++i) {
38         s[i].h = read(), s[i].v = read(); s[i].tot = A * s[i].h + B * s[i].v;
39         mv[i] = mh[i] = s[i];
40     }
41     sort(s + 1, s + n + 1, cmp1);
42     sort(mh + 1, mh + n + 1, cmp2);
43     sort(mv + 1, mv + n + 1, cmp3);
44     
45     int ans = 0;
46     for (int i = 1; i <= n; ++i) {
47         int p1 = 1, p2 = 1, cnt = 0;
48         LL minv = mv[i].v, limv = minv + C / B;
49         for (int j = 1; j <= n; ++j) {
50             LL minh = mh[j].h, limtot = C + A * minh + B * minv;
51             while (p1 <= n && s[p1].tot <= limtot) {
52                 if (s[p1].v >= minv && s[p1].v <= limv) cnt ++;
53                 p1 ++;
54             }
55             while (p2 <= n && mh[p2].h < minh) {
56                 if (mh[p2].v >= minv && mh[p2].v <= limv) cnt --;
57                 p2 ++;
58             }
59             ans = max(ans, cnt);
60         }
61     }
62     cout << ans;
63     return 0;
64 }
线性
 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<cmath>
 6 #include<cctype>
 7 #include<set>
 8 #include<queue>
 9 #include<vector>
10 #include<map>
11 using namespace std;
12 typedef long long LL;
13 
14 inline int read() {
15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
17 }
18 
19 const int N = 100005;
20 
21 struct Node{
22     int h, v; LL tot;
23 }s[N], mv[N], mh[N];
24 
25 bool cmp1(const Node &A, const Node &B) {
26     return A.tot < B.tot; 
27 }
28 bool cmp2(const Node &A, const Node &B) {
29     return A.h < B.h;
30 }
31 bool cmp3(const Node &A, const Node &B) {
32     return A.v < B.v;
33 }
34 priority_queue<int, vector<int>, greater<int> > q; 
35 int main() {
36     int n = read(); LL A = read(), B = read(), C = read();
37     for (int i = 1; i <= n; ++i) {
38         s[i].h = read(), s[i].v = read(); s[i].tot = A * s[i].h + B * s[i].v;
39         mv[i] = mh[i] = s[i];
40     }
41     sort(s + 1, s + n + 1, cmp1);
42     sort(mh + 1, mh + n + 1, cmp2);
43     sort(mv + 1, mv + n + 1, cmp3);
44     
45     int ans = 0;
46     for (int i = 1; i <= n; ++i) {
47         int p = 1, cnt = 0;
48         LL minv = mv[i].v;
49         for (int j = 1; j <= n; ++j) {
50             LL minh = mh[j].h, limtot = C + A * minh + B * minv;
51             while (p <= n && s[p].tot <= limtot) {
52                 if (s[p].v >= minv && s[p].h >= minh) cnt ++, q.push(s[p].h);
53                 p ++;
54             }
55             while (!q.empty() && q.top() < minh) cnt--, q.pop();
56             ans = max(ans, cnt);
57         }
58     }
59     cout << ans;
60     return 0;
61 }

 

posted @ 2018-11-29 10:40  MJT12044  阅读(183)  评论(0编辑  收藏  举报