思路:
贪心:最后的集合是最大值+前k小个
因为平均值时关于k的凹形函数,所以可以用三分求最小值
又因为后面的k肯定比前面的k大,所以又可以双指针
三分:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pli pair<ll,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=5e5+5; ll sum[N],cnt=0; int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout<<fixed<<setprecision(9); int q,t,x; cin>>q; while(q--){ cin>>t; if(t==1){ cin>>x; sum[++cnt]=sum[cnt-1]+x; } else{ int l=1,r=cnt-1,m1=(l+l+r)/3,m2=(l+r+r)/3; while(l<r){ if((double)(sum[m1]+x)/(m1+1)>=(double)(sum[m2]+x)/(m2+1)){ if(l==m1)break; else l=m1; } else{ if(r==m2)break; else r=m2; } m1=(l+l+r)/3,m2=(l+r+r)/3; } double tt=(double)(sum[l]+x)/(l+1); for(int i=l;i<=r;i++)tt=min(tt,(double)(sum[i]+x)/(i+1)); cout<<x-tt<<endl; } } return 0; }
双指针:
#include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mp make_pair #define pli pair<ll,int> #define mem(a,b) memset(a,b,sizeof(a)) const int N=5e5+5; ll sum[N],cnt=0,top=0,x; double cal(int l){ return (double)(x+sum[l])/(l+1); } int main(){ ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout<<fixed<<setprecision(9); int q,t; cin>>q; while(q--){ cin>>t; if(t==1){ cin>>x; sum[++cnt]=sum[cnt-1]+x; } else{ while(top<cnt){ if(cal(top+1)<cal(top))top++; else break; } cout<<x-cal(top)<<endl; } } return 0; }