リンク:https
://ac.nowcoder.com/acm/contest/7865/F出典:Niuke
题目引述
ルイス・L・ル・ロイ-ユニバースは、王宮から見た景観の改善を命じました。陛下は高い山を見ることを好みます。
チーフランドスケープマネージャーはルイのために山を上げるつもりです。彼は風景を単位正方形のグリッド上の平らな絵として表現します。いくつかの正方形はすでに岩で満たされていますが、他の正方形は空です。これにより、設計が大幅に簡素化されます。単位正方形は十分に小さく、王宮からの景観は滑らかなようです。
チーフランドスケープマネージャーは、ランドスケープの計画を立てています。幅の単位ごとに、岩で埋められたすべての柱の高さです。彼は、既存の風景の上に最大n平方単位の石を追加して、できるだけ高い山を作る予定です。残念ながら、石の山はかなり不安定です。石の単位正方形は、他の塗りつぶされた石または岩の正方形の上にのみ正確に配置できます。さらに、そのすぐ左下と右下の正方形はすでに塗りつぶされている必要があります。
あなたの仕事は、彼が構築できる最も高い山の最大の高さを決定するためにチーフ・ランドスケープマネージャーを支援することです。
输入描述:
入力ファイルの最初の行は、W 2つの整数を含んでいる-既存の景観の幅とn -の最大数追加する石の正方形(1≤w≤100000、0≤n≤1018)。
次の各w行には、単一の整数hi(既存のランドスケープ列の高さ(
1≤hi≤109 ))
が含まれます。石の安定的な方法で添加される。
示例1
输入
复制
8 4
3
4
2
1
3
3
2
4
出力の
コピー
5
実施例2
の入力
にコピー
3 100
3
3
3
出力
のコピー
4
質問:
グリッドを配置するには、左下と右下にグリッドが必要です。
最大n個のグリッドを追加して、最大の高さを見つけることができます。
アイデア:
高さが高いほど、より多くのグリッドを配置する必要があるため、この高さをダイシングすることを考えることができます。
ポジションiiの場合i、初期の高さがh [i] h [i]であると仮定しますh [ i ]、変更する高さは真ん中ですm i d、さらにいくつの正方形が必要かを把握する必要があります。この時とiiiが互いにx離れているグリッドの高さは、mid − xmid-x以上である必要があります。m i d−x、それ以外の場合は入力できません。この条件を満たす左右の最初の位置を見つければ、それを埋めることができます。見つからない場合は記入できません。
したがって、現在の位置から右への最初のjjを見つけるにはjがh [j] ≥mid−(j − i)h [j]≥mid-(ji)を満たす位置h [ j ]≥m i d−(j−I )の位置が設定され、左が第1の位置見つけるために株式会社をk满足h [k]≥mid−(i − k)h [k]≥mid-(ik)h [ k ]≥m i d−(私は−k )、次に[j、k] [j、k]と入力します[ j 、k ]部分。プレフィックスを使用して、充填部分に充填する量を計算します。
各番号はh [i] − ih [i] -iに対応しますh [ i ]−i(线段树1)与 h [ i ] + i h[i]+i h [ i ]+i(ラインセグメントツリー2)の場合、このプロセスはラインセグメントツリーによって維持できます。
iiの場合iこのポジションは中盤まで埋める必要がありますm i d、ラインセグメントツリー1の右側の最初の値がmid − imid-iより大きいことがわかります。m i d−iの点について、ラインセグメントツリー2で検出される座標の最初の値は、mid + i mid + iよりも大きくなります。m i d+私のポイント。あなたはどの部分を埋めるべきかを知ることができます。
この部分は、L [i] L [i]を維持するために直接前処理することもできます。L [ i ]はiiを意味します私は内に充填中旬中旬m i d、h [j] ≥mid−(i − j)h [j]≥mid-(ij)を満たす左側の最初のものに対応h [ j ]≥m i d−(私は−j )場所。R [i]はR [I]R [ i ]は半ばに埋められましたm i d、h [j] ≥mid−(j − i)h [j]≥mid-(ji)を満たす右側の最初のものに対応h [ j ]≥m i d−(j−i )位置
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <map>
#include <queue>
#include <cmath>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 7;
int n;
ll m,sum[maxn];
int a[maxn];
int L[maxn],R[maxn]; //这个点达到h高度所需改变的第一个左边下标位置,第一个右边下标位置
bool check(int mid) {
//期望高度
for(int i = 1;i <= n + 1;i++) {
L[i] = 0;
R[i] = n + 1;
}
for(int i = 1;i <= n;i++) {
if(i + mid - a[i] <= n && i + mid - a[i] >= i) {
L[i + mid - a[i]] = i;
}
}
for(int i = 1;i <= n;i++) {
if(i - mid + a[i] >= 1 && i - mid + a[i] <= i) {
R[i - mid + a[i]] = min(R[i - mid + a[i]],i);
}
}
for(int i = 1;i <= n;i++) L[i] = max(L[i],L[i - 1]);
for(int i = n;i >= 1;i--) R[i] = min(R[i],R[i + 1]);
for(int i = 1;i <= n;i++) {
if(L[i] == 0 || R[i] == n + 1) continue;
ll res = 1ll * (mid + mid - (i - L[i])) * (i - L[i] + 1) / 2;
res += 1ll * (mid - 1 + mid - 1 - (R[i] - i - 1)) * (R[i] - i - 1 + 1) / 2;
res -= sum[R[i]] - sum[L[i] - 1];
if(res <= m) return true;
}
return false;
}
int main() {
// freopen("landscape.in","r",stdin);
// freopen("landscape.out","w",stdout);
scanf("%d%lld",&n,&m);
int l = 0,r = 2e9;
for(int i = 1;i <= n;i++) {
scanf("%d",&a[i]);
l = max(l,a[i]);
sum[i] = sum[i - 1] + a[i];
}
int ans = l;
while(l <= r) {
int mid = (l + r) >> 1;
if(check(mid)) {
ans = mid;
l = mid + 1;
} else {
r = mid - 1;
}
}
printf("%d\n",ans);
return 0;
}