[Usaco2007 Jan]Cow School牛学校
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 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.
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
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(nlogn)。
十分优秀的思想。
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 }