CF212D 【Cutting a Fence】
由于在洛谷发布时,用了大量的LATEX,所以不想在博客园重新打一遍了。
#include <bits/stdc++.h> using namespace std; #define N 1000010 #define ll long long inline ll read(){ ll x = 0, s = 1; char c = getchar(); while(!isdigit(c)){ if(c == '-')s = -1; c = getchar(); } while(isdigit(c)){ x = x * 10 + (c ^ '0'); c = getchar(); } return x * s; } ll n, m, r[N], l[N], a[N]; ll s1[N], s2[N]; double ans[N]; void search(){ for(int i = n; i; i--){ /*向右找到第一个小于等于这个数的位置*/ if(a[i + 1] <= a[i]) r[i] = i + 1; else for(int j = r[i + 1]; j <= n + 1; j = r[j]) /*一直向右跑*/ if(a[j] <= a[i]){ r[i] = j; break; } } for(int i = 1;i <= n; i++){ /*同上,向左找*/ if(a[i - 1] < a[i]) l[i] = i - 1; else for(int j = l[i - 1]; j >= 0; j = l[j]) if(a[j] < a[i]) { l[i] = j; break; } } for(int i = 1;i <= n; i++){ /*换算成距离 L 和 R*/ l[i] = i - l[i]; r[i] = r[i] - i; } return ; } void prepare(){ /*进行差分以及预处理答案*/ for(int i = 1;i <= n; i++){ int x = l[i], y = r[i]; if(x > y) swap(x, y); /*保持 L < S*/ s1[1] += a[i]; s1[x + 1] -= a[i]; s2[x + 1] += a[i] * x; s1[y + 1] -= a[i]; s2[y + 1] += a[i] * y; s1[x + y] += a[i]; s2[x + y] -= a[i] * (x + y); } ll num1 = 0, num2 = 0; for(int i = 1;i <= n; i++){ num1 += s1[i], num2 += s2[i]; ans[i] = ((num1 * i + num2) * 1.00) / ((n - i + 1) * 1.00); /*预处理出所有答案*/ } return ; } int main(){ n = read(); for(int i = 1;i <= n; i++) a[i] = read(); a[n + 1] = (ll)(-(1 << 50));/*两端插入极小值,避免下一步越界或者出现错误*/ a[0] = (ll)(-(1 << 50)); search(); /*先搜索距离*/ prepare(); /*然后处理答案*/ m = read(); while(m--){ ll k = read(); printf("%.9lf\n", ans[k]); } return 0; }