uva1451 Average 单调栈求凸包
#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=1000100; const int INF=1<<29; int n,L; ll a[maxn],s[maxn]; struct Point { ll x,y; friend Point operator-(Point A,Point B) { return {A.x-B.x,A.y-B.y}; } friend ll operator*(Point A,Point B) { return 1LL*A.x*B.y-1LL*A.y*B.x; } void debug() { printf("%lld %lld\n",x,y); } };Point p[maxn],stk[maxn];int tp; Point ans,Max; int main() { freopen("in.txt","r",stdin); freopen("out.txt","w",stdout); int T;cin>>T; while(T--){ scanf("%d%d",&n,&L); REP(i,1,n) scanf("%1d",&a[i]); s[0]=0;REP(i,1,n) s[i]=s[i-1]+a[i]; REP(i,0,n) p[i]={i,s[i]}; //REP(i,0,n) p[i].debug();cout<<endl; tp=0; Max=(Point){1,0};ans=(Point){1,L}; int pre=1; REP(i,L,n){ while(tp>1&&(stk[tp]-stk[tp-1])*(p[i-L]-stk[tp])<0) tp--; //cout<<"tp:";stk[tp].debug(); //cout<<"p[i-L]:";p[i-L].debug(); //cout<<(stk[tp]-stk[tp-1])*(p[i-L]-stk[tp])<<endl; stk[++tp]=p[i-L]; if(pre>tp) pre=tp; int j=pre; Point tmp={1,0},res={1,L}; while(j<=tp){ if(tmp*(p[i]-stk[j])>0){ tmp=p[i]-stk[j]; res=(Point){stk[j].x+1,i}; pre=j; } else if(tmp*(p[i]-stk[j])==0){ if(i-(stk[j].x+1)<res.y-res.x){ tmp=p[i]-stk[j]; res=(Point){stk[j].x+1,i}; pre=j; } else if(i-(stk[j].x+1)==res.y-res.x){ if(stk[j].x+1<res.x){ tmp=p[i]-stk[j]; res=(Point){stk[j].x+1,i}; pre=j; } } } else break; j++; } if(Max*tmp>0) Max=tmp,ans=res; //puts("stk:");REP(i,1,tp) stk[i].debug(); } printf("%lld %lld\n",ans.x,ans.y); //cout<<Max.y<<"/"<<Max.x<<endl; } return 0; } /** 直接搞段平均值是很难的,但是平均值可以转化为段和,再转化为前缀和, 再由构造(i,s[i])的图像通过斜率观察平均值,然后用单调栈维护单调性求个上(下)凸包就可以了。 本来以为算法出错了,对拍了半天原来是题目看错了。。。fuck。。 */
没有AC不了的题,只有不努力的ACMER!