【BZOJ 3316】JC loves Mkk 01分数规划+单调队列
单调栈
不断吞入数据维护最值,数据具有单调性但不保证位置为其排名,同时可以按照进入顺序找出临近较值
单调队列
队列两端均可删除数据但只有队末可以加入数据,仍然不断吞入数据但同时可以额外刨除一些不符合条件的数据,强调额外刨除数据按照进入顺序,维护在有额外刨除条件下的最值,数据具有单调性但不保证位置为其排名也不保证都是合法,丧失可以按照进入顺序找出临近较值的能力
#include <cstdio> typedef long double ld; typedef long long ll; const ld eps=1e-8; const int N=100010; int q[N]; ld key[N<<1]; int head,tail; int n,L,R; int a[N],ans1,ans2; inline bool check(ld x){ for(int i=1;i<=n;++i) key[i]=key[i+n]=(ld)a[i]-x; for(int i=2;i<=(n<<1);++i) key[i]+=key[i-1]; head=1,tail=0; for(int i=L;i<=R;i+=2){ while(head<=tail&&key[q[tail]]<key[i])tail--; q[++tail]=i; } if(key[q[head]]>0){ ans1=1,ans2=q[head]; return true; } for(int i=3;i<=n;i+=2){ while(head<=tail&&key[q[tail]]<key[i+R-1])tail--; q[++tail]=i+R-1; while(head<=tail&&q[head]<(i+L-1))head++; if(key[q[head]]-key[i-1]>0){ ans1=i,ans2=q[head]; return true; } } head=1,tail=0; for(int i=L+1;i<=R+1;i+=2){ while(head<=tail&&key[q[tail]]<key[i])tail--; q[++tail]=i; } if(key[q[head]]-key[1]>0){ ans1=2,ans2=q[head]; return true; } for(int i=4;i<=n;i+=2){ while(head<=tail&&key[q[tail]]<key[i+R-1])tail--; q[++tail]=i+R-1; while(head<=tail&&q[head]<(i+L-1))head++; if(key[q[head]]-key[i-1]>0){ ans1=i,ans2=q[head]; return true; } } return false; } inline ll GCD(ll x,ll y){ return x==0?y:GCD(y%x,x); } int main(){ scanf("%d%d%d",&n,&L,&R),L+=L&1,R-=R&1; for(int i=1;i<=n;++i)scanf("%d",&a[i]); for(ld l=0,r=1e9,mid;l+eps<=r;mid=(l+r)/2.,check(mid)?l=mid:r=mid); if(ans1==0){printf("0");return 0;} ll s=0,b=ans2-ans1+1; for(int i=ans1;i<=ans2;++i)s+=a[i>n?i-n:i]; ll gcd=GCD(s,b);s/=gcd,b/=gcd; if(b==1)printf("%lld",s); else printf("%lld/%lld",s,b); return 0; }
苟利国家生死以, 岂因祸福避趋之。