zoukankan      html  css  js  c++  java
  • [SCOI2007]组队

    嘟嘟嘟

    这题有人说部分分O(n3)暴力,然而我暴力都没写过,调了半天也没用……还是看题解吧

    首先,咱把A * ( h – minH ) + B * ( s – minS ) <= C 变个型,得到 A * h + B * s - C <= A * minH + B * minS. 令 sum = A * h + B * s - C,如果我们把所有球员按sum排序,就能保证取球员的时候是单调的,如果 i 能取,则 j (j < i) 一定能取。

    然后我们第一层循环枚举minS,第二层循环枚举minH,然后设两个指针L, R,表示当前符合sum <= A * minH + B * minS的区间,但同时我们还要保证h >= minH && s >= minS,而且根据h >= minH还要保证,s <= minS + C / B.于是就有一个很【强】的做法,我们先把符合的条件的s添加进去,再把队列中不符合条件的h踢出。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #include<cmath>
     5 #include<cstring>
     6 #include<cstdlib>
     7 #include<vector>
     8 #include<queue>
     9 #include<stack>
    10 #include<cctype>
    11 using namespace std;
    12 #define enter puts("")
    13 #define space putchar(' ')
    14 #define Mem(a) memset(a, 0, sizeof(a))
    15 typedef long long ll;
    16 typedef double db;
    17 const int INF = 0x3f3f3f3f;
    18 const db eps = 1e-8;
    19 const int maxn = 5e3 + 5;
    20 inline ll read()
    21 {
    22     ll ans = 0;
    23     char ch = getchar(), last = ' ';
    24     while(!isdigit(ch)) last = ch, ch = getchar();
    25     while(isdigit(ch)) ans = (ans << 3) + (ans << 1) + ch - '0', ch = getchar();
    26     if(last == '-') ans = -ans;
    27     return ans;
    28 }
    29 inline void write(ll x)
    30 { 
    31     if(x < 0) putchar('-'), x = -x;
    32     if(x >= 10) write(x / 10);
    33     putchar(x % 10 + '0');
    34 }
    35 
    36 int n;
    37 ll A, B, C;
    38 struct Node
    39 {
    40     int h, s; ll sum;
    41 }Sum[maxn], H[maxn], S[maxn];
    42 bool cmp1(Node a, Node b) {return a.sum < b.sum;}
    43 bool cmp2(Node a, Node b) {return a.h < b.h;}
    44 bool cmp3(Node a, Node b) {return a.s < b.s;}
    45 
    46 int ans = 0;
    47 
    48 int main()
    49 {
    50     n = read(); A = read(); B = read(); C = read();
    51     for(int i = 1; i <= n; ++i)
    52     {
    53         Sum[i].h = read(), Sum[i].s = read(); Sum[i].sum = (ll)A * Sum[i].h + (ll)B * Sum[i].s - C;
    54         H[i].h = Sum[i].h; H[i].s = Sum[i].s; H[i].sum = Sum[i].sum;
    55         S[i].h = Sum[i].h; S[i].s = Sum[i].s; S[i].sum = Sum[i].sum;
    56     } 
    57     sort(Sum + 1, Sum + n + 1, cmp1);
    58     sort(H + 1, H + n + 1, cmp2);
    59     sort(S + 1, S + n + 1, cmp3);
    60     for(int i = 1; i <= n; ++i)        //枚举minS 
    61     {
    62         int L = 0, R = 0, cnt = 0;
    63         ll Mins = S[i].s;
    64         ll Lims = Mins + C / B;
    65         for(int j = 1; j <= n; ++j)        //枚举minH 
    66         {
    67             ll Limsum = A * H[j].h + B * Mins;
    68             while(R < n && Sum[R + 1].sum <= Limsum)    //合法区间,但不能保证s,h符合 
    69             {
    70                 R++;
    71                 if(Mins <= Sum[R].s && Sum[R].s <= Lims) cnt++;    //符合条件的s 
    72             }
    73             while(L < n && H[L + 1].h < H[j].h)        //维护合法区间左端点  
    74             {
    75                 L++;
    76                 if(Mins <= H[L].s && H[L].s <= Lims) cnt--;    //踢出不符合的h
    77                 //因为[L, R]中可能有cnt之外的,所以要判断哪些属于cnt,踢出时再cnt-- 
    78             }
    79             ans = max(ans, cnt);
    80         }
    81     }
    82     write(ans); enter;
    83     return 0;
    84 }
    View Code
  • 相关阅读:
    说文解字 —— 拆字
    4K 对齐与固态硬盘检测工具
    硬盘分区(主分区、扩展分区、逻辑分区)
    python+caffe训练自己的图片数据流程
    亲和数(220/284)
    浅谈多进程多线程的选择
    Linux下的多线程编程
    LINUX-进程的概念
    Linux终端那件事儿
    Linux的终端类型
  • 原文地址:https://www.cnblogs.com/mrclr/p/9536685.html
Copyright © 2011-2022 走看看