bzoj2216: [Poi2011]Lightning Conductor
Description
已知一个长度为n的序列a1,a2,...,an。
对于每个1<=i<=n,找到最小的非负整数p满足 对于任意的j, aj < = ai + p - sqrt(abs(i-j))
Input
第一行n,(1<=n<=500000)
下面每行一个整数,其中第i行是ai。(0<=ai<=1000000000)
Output
n行,第i行表示对于i,得到的p
Sample Input
6
5
3
2
4
2
4
5
3
2
4
2
4
Sample Output
2
3
5
3
5
4
3
5
3
5
4
题解:
http://hzwer.com/5273.html
code:
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<cassert> 5 #include<cstring> 6 #include<algorithm> 7 using namespace std; 8 char ch; 9 bool ok; 10 void read(int &x){ 11 for (ok=0,ch=getchar();!isdigit(ch);ch=getchar()) if (ch=='-') ok=1; 12 for (x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar()); 13 if (ok) x=-x; 14 } 15 const int maxn=500005; 16 int n,a[maxn],ans[maxn],root[maxn]; 17 double calc(int j,int i){return a[j]-a[i]+sqrt(i-j);} 18 struct Stack{ 19 int top,pos; 20 struct Data{ 21 int l,r,id; 22 }s[maxn],tmp; 23 void init(){s[top=1]=(Data){2,n,1},pos=1;} 24 bool cmp(int a,int x,int y){return calc(x,a)>calc(y,a);} 25 int get(int id){ 26 int l=tmp.l,r=tmp.r,m,a=tmp.id; 27 while (l<r){ 28 m=((l+r)>>1)+1; 29 if (cmp(m,a,id)) l=m; else r=m-1; 30 } 31 return l; 32 } 33 void push(int id){ 34 while (top>=pos&&!cmp(s[top].l,s[top].id,id)) top--; 35 if (top>=pos){ 36 tmp=s[top--]; 37 int m=get(id); 38 if (tmp.l<=m) s[++top]=(Data){tmp.l,m,tmp.id}; 39 if (m<n) s[++top]=(Data){m+1,n,id}; 40 } 41 else s[++top]=(Data){id+1,n,id}; 42 } 43 int query(int x){ 44 while (x>s[pos].r) pos++; 45 s[pos].l=x+1; 46 return ceil(calc(s[pos].id,x)); 47 } 48 }stack; 49 int main(){ 50 read(n); 51 for (int i=1;i<=n;i++) read(a[i]); 52 stack.init(); 53 for (int i=2;i<=n;i++) ans[i]=max(0,stack.query(i)),stack.push(i); 54 for (int i=1,j=n;i<j;i++,j--) swap(a[i],a[j]); 55 stack.init(); 56 for (int i=2;i<=n;i++) ans[n-i+1]=max(ans[n-i+1],stack.query(i)),stack.push(i); 57 for (int i=1;i<=n;i++) printf("%d\n",ans[i]); 58 return 0; 59 }