[UOJ#245][UER#7]天路(近似算法)
允许5%的相对误差,意味着我们可以只输出$\log_{1.05} V$种取值并保证答案合法。并且注意到答案随着区间长度而单增,故取值不同的答案区间是$O(\log_{1.05} V)$的。
于是初始x=0,每次x=max(x+1,x*1.05),再用单调队列$O(n)$找出当前x能更新的区间即可。总复杂度$O(n\log_{1.05}V)$
1 #include<cstdio> 2 #include<algorithm> 3 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 4 using namespace std; 5 6 const int N=100010; 7 int n,h1,h2,r1,r2,a[N],q1[N],q2[N],x,l=2,r; 8 9 int main(){ 10 scanf("%d",&n); 11 rep(i,1,n) scanf("%d",&a[i]); 12 for(; l<=n; x=max(x+1,int(x*1.05))){ 13 h1=h2=1; r=r1=r2=0; int now=1; 14 rep(i,1,n){ 15 while(r1>=h1 && a[q1[r1]]<a[i]) r1--; 16 while(r2>=h2 && a[q2[r2]]>a[i]) r2--; 17 q2[++r2]=q1[++r1]=i; 18 for(; a[q1[h1]]-a[q2[h2]]>x; now++){ 19 if(q1[h1]==now)h1++; 20 if(q2[h2]==now)h2++; 21 } 22 r=max(r,i-now+1); 23 } 24 for(; l<=r; l++)printf("%d\n",x); 25 } 26 return 0; 27 }