bzoj 1701 [Usaco2007 Jan]Cow School牛学校

[Usaco2007 Jan]Cow School牛学校

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 175  Solved: 83
[Submit][Status][Discuss]

Description

Bessy 正在上学并且分数还不错. 她考了N (一个数据中1 <= N <= 50,000, 其余数据 1 <= N <= 50,00) 次试,每次考试得分为T_i, 满分为P_i(0 <= T_i <= P_i < 40,000; 0 < P_i). 在计算总分时,她的老师先将把分数(P_i/T_i)最高的D个试卷去掉,然后将其余P_i 的和除以其余T_i的和作为Bessy的分数. Bessy精通数学,所以很快发觉这并没有想象中那么好. Bessy想告诉她的老师所有附和以下条件的D: 如果令一组(D个)分数去掉,她的分数回比老师算出来的更高. Bessy 很惊讶地发现她没有两次考试得分百分点是一样的.

Input

*第一行: N

*第2..N+1行: 第i行里有 T_i 和 P_i.

Output

* 第一行: K, 符合条件的D的个数.

*第2..K+1行: 按递增顺序,每行一个符合条件的D.

Sample Input

5
1 2
5 9
3 8
4 10
1 3

输入解释:

Bessy 考了5门试, 分数分别为1/2, 5/9, 3/8, 4/10, 1/3.

Sample Output

2
1
2
 
题解:

枚举剩下的分数个数kk,设最高的kk个分数和的分子分母分别为UU和DD。

那么在选了的里面找到A=min(Dt[x]Up[x])A=min(Dt[x]−Up[x]),没选的里面找到B=max(Dt[x]Up[x])B=max(Dt[x]−Up[x])。

如果A<BA<B,则可以更大。

对于A,BA,B的计算,可以利用决策单调性分治求解。

时间复杂度O(nlogn)O(nlog⁡n)。

十分优秀的思想。

 1 #include<cstring>
 2 #include<cmath>
 3 #include<iostream>
 4 #include<algorithm>
 5 #include<cstdio>
 6 
 7 #define ll long long
 8 #define ls tr[p].l
 9 #define rs tr[p].r
10 #define N 100007
11 using namespace std;
12 const ll inf=2000000000000010;
13 inline ll read()
14 {
15     ll x=0,f=1;char ch=getchar();
16     while(ch<'0'||ch>'9'){if (ch=='-')f=-1;ch=getchar();}
17     while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
18     return x*f;
19 }
20 
21 int n,ans,q[N];
22 ll f[N],g[N];
23 struct Node
24 {
25     int t,p;
26 }a[N],b[N];
27 
28 inline bool cmp(Node a,Node b)
29 {
30     return a.t*b.p>b.t*a.p;
31 }
32 void getf(int l,int r,int dl,int dr)
33 {
34     int m=(l+r)>>1,dm;
35     f[m]=inf;
36     for(int i=dl;i<=m&&i<=dr;i++)
37     {
38         ll t=1LL*a[i].t*b[m].p-1LL*a[i].p*b[m].t;
39         if(t<f[m])f[m]=t,dm=i;
40       }
41     if(l<m)getf(l,m-1,dl,dm);
42     if(r>m)getf(m+1,r,dm,dr);
43 }
44 void getg(int l,int r,int dl,int dr)
45 {
46     int m=(l+r)>>1,dm;
47     g[m]=-inf;
48       for(int i=dr;i>m&&i>=dl;i--)
49     {    
50         ll t=1LL*a[i].t*b[m].p-1LL*a[i].p*b[m].t;
51         if(t>g[m])g[m]=t,dm=i;
52       }
53       if(l<m)getg(l,m-1,dl,dm);
54       if(r>m)getg(m+1,r,dm,dr);
55 }
56 int main()
57 {
58     scanf("%d",&n);
59       for(int i=1;i<=n;i++)
60         scanf("%d%d",&a[i].t,&a[i].p);
61       sort(a+1,a+n+1,cmp);
62       for(int i=1;i<=n;i++)
63           b[i].t=b[i-1].t+a[i].t,b[i].p=b[i-1].p+a[i].p;
64       getf(1,n-1,1,n),getg(1,n-1,1,n);
65       for(int i=1;i<n;i++)
66           if(f[i]<g[i]) q[++ans]=n-i;
67     printf("%d
",ans);
68     for(int i=ans;i;i--)
69         printf("%d
",q[i]);
70 }
原文地址:https://www.cnblogs.com/fengzhiyuan/p/8065972.html