jsk Star War (線段樹維護區間最小最大值 + 二分)
阿新 • • 發佈:2018-11-01
Description
公元20XX年,人類與外星人之間的大戰終於爆發。
現有一個人類軍團,由n名士兵組成,第i個士兵的戰鬥力值對應一個非負整數ai (1 \leq i \leq n1≤i≤n)。
有一天,某個戰力爆表的外星人NaN單獨向地球人宣戰,已知它的戰力值為k (1 \leq k \leq 1e131≤k≤1e13)。現在該軍團指揮官決定派遣編號在某個區間(l,r)內的士兵去與敵方決鬥。由於對手的不一般,現規定一個奇怪的戰力值計算公式:f(l,r)=[max(l,r)-min(l,r)]*(r-l+1)f(l,r)=[max(l,r)−min(l,r)]∗(r−l+1),(1 \leq l < r \leq n)(1≤l <r≤n)。
即只有當f(l,r) \geq kf(l,r)≥k時才能戰勝敵人。請聰明的你來計算至少需要派出多少名士兵才能戰勝敵人。
Input
第一行輸入兩個整數nn,kk,(1 \leq n \leq 2e5,1 \leq k \leq 1e131≤n≤2e5,1≤k≤1e13),分別代表軍團士兵個數和敵人戰力值;第二行輸入nn個整數,表示第i(1\leq i \leq n)i(1≤i≤n)名士兵的戰力值(0 \leq ai \leq 1e9)(0≤ai≤1e9)。
Output
答案輸出一個正整數表示應派出士兵的數量,如果不存在則輸出-1−1。
輸出時每行末尾的多餘空格,不影響答案正確性
樣例輸入複製
5 3
1 2 3 4 5
樣例輸出複製
3
解題報告:
AC程式碼:
#include<bits/stdc++.h> #define ll long long using namespace std; const ll MAX = 2e5 + 5; int n; ll a[MAX],k; struct TREE { int l,r; ll val,maxx,minn; } tree[MAX * 4]; void pushup(int cur) { tree[cur].val = tree[cur*2].val + tree[cur*2+1].val; tree[cur].maxx = max(tree[cur*2].maxx , tree[cur*2+1].maxx); tree[cur].minn = min(tree[cur*2].minn , tree[cur*2+1].minn); } void build(int l,int r,int cur) { tree[cur].l=l;tree[cur].r=r; if(l == r) { tree[cur].val = tree[cur].maxx = tree[cur].minn = a[l]; return ; } int m = (l+r)/2; build(l,m,cur*2); build(m+1,r,cur*2+1); pushup(cur); } ll querymax(int pl,int pr,int cur) { if(pl <= tree[cur].l && pr >= tree[cur].r) return tree[cur].maxx; ll res = 0; if(pl <= tree[cur*2].r) res = max(res,querymax(pl,pr,cur*2)); if(pr >= tree[cur*2+1].l) res = max(res,querymax(pl,pr,cur*2+1)); return res; } ll querymin(int pl,int pr,int cur) { if(pl <= tree[cur].l && pr >= tree[cur].r) return tree[cur].minn; ll res = LLONG_MAX; if(pl <= tree[cur*2].r) res = min(res,querymin(pl,pr,cur*2)); if(pr >= tree[cur*2+1].l) res = min(res,querymin(pl,pr,cur*2+1)); return res; } bool fit(int x) { for(int i = 1; i<=n-x+1; i++) { if((querymax(i,i+x-1,1) - querymin(i,i+x-1,1)) * x >= k) return 1; } return 0 ; } int main() { cin>>n>>k; for(int i = 1; i<=n; i++) cin>>a[i]; build(1,n,1); int l = 0;int r = n; int mid = (l+r)/2; while(l<r) { mid = (l+r)/2; if(fit(mid)) r=mid; else l=mid+1; } printf("%d\n",l); return 0 ; }