LA 4726 Average(单调队列)

来源:互联网 发布:scratch儿童学编程 编辑:程序博客网 时间:2024/06/06 13:03

题意:求连续的子序列使得平均数最大。


分析:按照《浅谈数形结合思想在信息学竞赛中的应用》中的做法,维护一个下凸的决策区间,但是注意原作者提到单调栈做法并不是指决策是随着右端点单调的,而是指最优解是随着左端点单调的。




#include<iostream>#include<string>#include<algorithm>#include<cstdlib>#include<cstdio>#include<set>#include<map>#include<vector>#include<cstring>#include<stack>#include<cmath>#include<queue>#define INF 0x3f3f3f3f#define eps 1e-9using namespace std;int T,l,n,x,y,ans,Stack[100005],f[100005];char s[100005];long long jud(int x1,int y1,int x2,int y2,int x3,int y3){return 1ll*(x1-x3)*(y2-y3)-1ll*(y1-y3)*(x2-x3);}double dis(int a,int b)  {  return (f[b]-f[a])*1.0/(b-a);  }  int main(){scanf("%d",&T);while(T--){scanf("%d%d",&n,&l);scanf("%s",s+1);for(int i = 1;i <= n;i++) f[i] = s[i] - '0' + f[i-1];int front = 1,tail = 1,ans1 = 0,ans2 = l;double ans = 0;for(int i = l;i <= n;i++){while(tail - front >= 2 && dis(Stack[tail-1],i-l) <= dis(Stack[tail-1],Stack[tail-2])) tail--;Stack[tail++] = i-l;int left = front,right = tail-1;while(left != right){int mid = (left+right)/2 + 1;if(jud(Stack[mid-1],f[Stack[mid-1]],Stack[mid],f[Stack[mid]],i,f[i]) >= 0) left = mid;else right = mid - 1;}if(dis(Stack[right],i) > ans){ans = (1.0*f[i]-f[Stack[right]])/(i-1.0*Stack[right]);ans1 = Stack[right];ans2 = i;}else  if(dis(Stack[right],i) == ans && ans2 - ans1 > i - Stack[right]) { ans1 = Stack[right];ans2 = i; }}cout<<ans1+1<<" "<<ans2<<endl;} }


0 0
原创粉丝点击