zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Linux 常用指令【持续更新】
    我的 MyBatis 实现的 Dao 层
    Mybatis 点点滴滴
    Redis 初识
    Mybatis 映射关系
    Mybatis 类属性和字段映射小小分析
    Mybatis 中 sql 语句的占位符 #{} 和 ${}
    使用 Maven 管理项目
    Maven 项目依赖 pom 文件模板
    Maven 私服安装和启动
  • 原文地址:https://www.cnblogs.com/mjtcn/p/10036778.html
Copyright © 2011-2022 走看看