[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 }

猜你喜欢

转载自www.cnblogs.com/HocRiser/p/10198742.html
245