BZOJ1701 : [Usaco2007 Jan]Cow School牛学校

时间:2021-04-23 07:14:16

枚举剩下的分数个数$k$,设最高的$k$个分数和的分子分母分别为$U$和$D$。

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

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

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

时间复杂度$O(n\log n)$。

#include<cstdio>
#include<algorithm>
typedef long long ll;
const int N=50010;
const ll inf=1LL<<60;
int n,i,ans,q[N];ll f[N],g[N];
struct P{int t,p;}a[N],b[N];
inline bool cmp(const P&a,const P&b){return a.t*b.p>b.t*a.p;}
void getf(int l,int r,int dl,int dr){
int m=(l+r)>>1,dm;
f[m]=inf;
for(int i=dl;i<=m&&i<=dr;i++){
ll t=1LL*a[i].t*b[m].p-1LL*a[i].p*b[m].t;
if(t<f[m])f[m]=t,dm=i;
}
if(l<m)getf(l,m-1,dl,dm);
if(r>m)getf(m+1,r,dm,dr);
}
void getg(int l,int r,int dl,int dr){
int m=(l+r)>>1,dm;
g[m]=-inf;
for(int i=dr;i>m&&i>=dl;i--){
ll t=1LL*a[i].t*b[m].p-1LL*a[i].p*b[m].t;
if(t>g[m])g[m]=t,dm=i;
}
if(l<m)getg(l,m-1,dl,dm);
if(r>m)getg(m+1,r,dm,dr);
}
int main(){
scanf("%d",&n);
for(i=1;i<=n;i++)scanf("%d%d",&a[i].t,&a[i].p);
std::sort(a+1,a+n+1,cmp);
for(i=1;i<=n;i++)b[i].t=b[i-1].t+a[i].t,b[i].p=b[i-1].p+a[i].p;
getf(1,n-1,1,n),getg(1,n-1,1,n);
for(i=1;i<n;i++)if(f[i]<g[i])q[++ans]=n-i;
for(printf("%d\n",ans),i=ans;i;i--)printf("%d\n",q[i]);
return 0;
}