BZOJ1071: [SCOI2007]組隊【雙指針】【思惟好題】

Description

  NBA每一年都有球員選秀環節。一般用速度和身高兩項數據來衡量一個籃球運動員的基本素質。假如一支球隊裏速度最慢的球員速度爲minV,身高最矮的球員高度爲minH,那麼這支球隊的全部隊員都應該知足: A * ( height
– minH ) + B * ( speed – minV ) <= C 其中A和B,C爲給定的經驗值。這個式子很容易理解,若是一個球隊的球員速度和身高差距太大,會形成配合的不協調。 請問做爲球隊管理層的你,在N名選秀球員中,最多能有多少名符合條件的候選球員。c++

Input

  第一行四個數N、A、B、C 下接N行每行兩個數描述一個球員的height和speed數組

Output

  最多候選球員數目。spa

Sample Input

4 1 2 10
5 1
3 2
2 3
2 1指針

Sample Output

4code

HINT

數據範圍: N <= 5000 ,height和speed不大於10000。A、B、C在長整型之內。排序


思路

這題也真是夠神仙的隊列

首先把式子變成這樣ip

$Ax+By-C\le Aminx + Bminy $input

而後就從新取一個權值叫作\(val=Ax+By-C\)it

把原數組複製兩遍,一個按照x排序,一個按照val排序

而後咱們先枚舉miny,而後在內層枚舉minx,可是同時怎麼維護答案?

咱們用一個指針掃val加入答案,並用一個指針掃x刪除答案

我第一次看到的時候心情就是wtf?

確實很神奇

如今咱們考慮加入答案的限制,首先y確定是要大於等於miny的,可是y應該有一個上界,否則\(y-miny\)太大致使在知足\(val\le Aminx+Bminy\)的條件下\(x< minx\)

既然不能讓x超界,也就是要知足\(minx\le x\),那麼就必定有

\(By\le Bminy + C\)

也就是說\(miny\le y\le miny + \frac{C}{B}\)

這樣就能夠同時掃按照x排序的隊列來把x不知足的都刪掉了(由於y對於全局的限制都是相等的)

???

好像推不過來吧,不過沒事,在這道題裏面是對的

如今來考慮另外一個事情:會不會有沒有統計貢獻的被刪除貢獻?

不可能的

被刪除貢獻的時候須要知足\(x<minx\)\(min\le y\le miny+\frac{C}{B}\)

顯然是知足\(Ax+By\le Aminx+Bminy+C\)

那不就必定會在上面統計貢獻嗎?

因此就成立了。。。而後其實你也能夠根據剛剛這個式子把\(By\le Bminy + C\)理解爲讓刪除不重不漏的條件


#include<bits/stdc++.h>

using namespace std;

const int N = 5010;

int n, A, B, C;
int ans;

struct Point {
  int x, y, val;
  Point() {}
  Point(int x, int y, int val): x(x), y(y), val(val) {}
} p[N], q[N];

bool cmp1(const Point a, const Point b) {
  return a.x < b.x;
}

bool cmp2(const Point a, const Point b) {
  return a.val < b.val;
}

int main() {
  scanf("%d %d %d %d", &n, &A, &B, &C);
  for (int i = 1; i <= n; i++) {
    int x, y;
    scanf("%d %d", &x, &y);
    p[i] = q[i] = Point(x, y, A * x + B * y - C);
  }
  sort(p + 1, p + n + 1, cmp1);
  sort(q + 1, q + n + 1, cmp2);
  for (int i = 1; i <= n; i++) {
    int tp = 0, tq = 0, cur = 0;
    int dn = p[i].y, up = C / B + p[i].y;
    for (int j = 1; j <= n; j++) {
      int limit = A * p[j].x + B * p[i].y;
      while (tp < n && p[tp + 1].x < p[j].x) {
        ++tp;
        cur -= dn <= p[tp].y && p[tp].y <= up;
      }
      while (tq < n && q[tq + 1].val <= limit) {
        ++tq;
        cur += dn <= q[tq].y && q[tq].y <= up;
      }
      ans = max(ans, cur);
    }
  }
  printf("%d", ans);
  return 0;
}
相關文章
相關標籤/搜索