1. 程式人生 > >51nod 1349 最大值

51nod 1349 最大值

htm nbsp can max scanf () fin put tdi

題目看這裏

找到每個元素g[i]作為最大值的區間[L,R],那麽以他為最大值的區間數有(i-L+1)*(R-i+1)個。

為了加速,以k為最大值的區間數放入H[k],再以此統計一個前綴和,更新入H。那麽>=s的區間個數就是H[1e5]-H[s-1]。

留意:為了避免區間重復,對於同樣的元素,左邊遇到時繼續延伸,用<=號,右邊遇到時不再延伸,用<號。

比如{3,3},防止既以第一個3為基準統計了區間[1,2],又以第2個3為基準統計了[1,2]。

另,統計區間數時,因為有重復元素,比如以k為最大值的區間數為cnt,那麽應該是H[k]+=cnt。而非H[k]=cnt。

#include <stdio.h>
#include 
<string.h> #define ll long long const ll maxN=1e5+5; ll N, M, K, T; ll g[maxN], h[maxN]; ll L[maxN], R[maxN]; int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif scanf("%lld", &N); for (ll i = 1; i <= N; ++i) scanf("%lld", &g[i]); scanf(
"%lld", &K); for (ll i = 1; i <= N; ++i) { L[i] = i - 1; R[i] = i + 1; } for (ll i = 1; i <= N; ++i) while (L[i] && g[L[i]] <= g[i]) L[i] = L[L[i]]; for (ll i = N; i >= 1; --i) while (R[i] <= N && g[R[i]] < g[i]) R[i]
= R[R[i]]; /* for (ll i = 1; i <= N; ++i) printf("%lld %lld\n", L[i], R[i]); puts(""); */ memset(h, 0, sizeof h); for (ll i = 1; i <= N; ++i) h[g[i]] += (i - L[i]) * (R[i] - i); for (ll i = 1; i < maxN; ++i) h[i] += h[i - 1]; for (ll i = 0, s; i < K; ++i) { scanf("%lld", &s); printf("%lld\n", h[maxN - 1] - h[s - 1]); } return 0; }

51nod 1349 最大值