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

    Description

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

    Input

      第一行四个数N、A、B、C 下接N行每行两个数描述一个球员的height和speed

    Output

      最多候选球员数目。

    Sample Input

    4 1 2 10
    5 1
    3 2
    2 3
    2 1
    

    Sample Output

    4
    

    Solution

    把式子化开,可以得到:

    [Acdot h+Bcdot sleqslant Acdot mnh+Bcdot mns+C ]

    然后我们就得到了一个(O(n^3))的做法:枚举(mnh,mns),然后枚举每一个合不合法。

    考虑这个怎么优化,首先枚举最小值的时候从小到大枚举,那么枚举(mns)的时候不等式的右边就会单调递增,那么我们可以按照左边排序,然后从小到大加。

    注意到这里还要两个限制:(hgeqslant mnh,sgeqslant mns),然后就有一个很神奇的做法:

    先不考虑(s)带来的影响,那么对于(h),显然要满足(mnhleqslant h leqslant mnh+C/A),然后把满足这些条件的加进去,

    对于(s),如果满足以上条件,但是(s<mns),那么就把这个删掉。

    然后合法的一定是连续一段,所以上面的做法是对的。

    可以发现以上都是单调的,所以总复杂度(O(n^2))

    #include<bits/stdc++.h>
    using namespace std;
     
    #define int long long 
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 2e5+10;
    
    int n,A,B,C,tx[maxn],ans,q[maxn];
    struct data {int x,y,sum;}a[maxn],b[maxn],c[maxn];
    
    int cmpx(data x,data y) {return x.x<y.x;}
    int cmpy(data x,data y) {return x.y<y.y;}
    int cmpsum(data x,data y) {return x.sum<y.sum;}
    
    signed main() {
    	read(n),read(A),read(B),read(C);
    	for(int i=1;i<=n;i++) read(a[i].x),read(a[i].y),b[i].x=c[i].x=a[i].x,b[i].y=c[i].y=a[i].y;
    	for(int i=1;i<=n;i++) c[i].sum=c[i].x*A+c[i].y*B;
    	sort(a+1,a+n+1,cmpx);
    	sort(b+1,b+n+1,cmpy);
    	sort(c+1,c+n+1,cmpsum);
    	for(int i=1;i<=n;i++) {
    		int mn=a[i].x,mx=a[i].x+C/A,p1=0,p2=0,cnt=0;
    		for(int j=1;j<=n;j++) {
    			int lim=C+a[i].x*A+b[j].y*B;
    			while(p1<n&&c[p1+1].sum<=lim)
    				p1++,cnt+=(c[p1].x>=mn&&c[p1].x<=mx);
    			while(p2<n&&b[p2+1].y<b[j].y)
    				p2++,cnt-=(b[p2].x>=mn&&b[p2].x<=mx);
    			ans=max(ans,cnt);
    		}
    	}write(ans);
    	return 0;
    }
    
  • 相关阅读:
    hdu7047 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1004 Link with Balls
    hdu7115 Vertex Deletion
    CF1552B B. Running for Gold
    hdu7055 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1012 Yiwen with Sqc
    hdu7050 /2021“MINIEYE杯”中国大学生算法设计超级联赛(7) 1007 Link with Limit
    CF 1560E E. Polycarp and String Transformation(思维)
    CF 1542C C. Strange Function
    STL 算法 std::distance
    STL 算法 std::accumulate
    std::get<C++11多线程库~线程管理>(08):转移线程所有权(2)
  • 原文地址:https://www.cnblogs.com/hbyer/p/10418325.html
Copyright © 2011-2022 走看看