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

51 Nod 1349 最大值

isdigit void 個數字 courier ray www. 要求 .html alt

1349 最大值

有一天,小a給了小b一些數字,讓小b幫忙找到其中最大的數,由於小b是一個程序猿,當然寫了一個代碼很快的解決了這個問題。

這時,邪惡的小c又出現了,他問小b,假如我只需要知道這些數字中的某個區間的最大值,你還能做嘛?

小b經過七七四十九天的思考,終於完美的解決了這道題目,這次,他想也讓小c嘗嘗苦頭,於是他問小c,我現在想知道存在多少不同的區間的最大值大於等於k,你還能做嗎?

這次,小c犯了難,他來請教身為程序猿的你。

Hint:一個區間指al,al+1,…,ar這一段的數且l<=r,一個區間的最大值指max{al,al+1,…,ar},兩個區間不同當且僅當[l1,r1],[l2,r2]中l1不等於l2或r1不等於r2

Input
第一行讀入一個正整數n(1<=n<=100000),表示有n個數字。
接下來一行讀入n個正整數ai(1<=ai<=100000)
接下來一行一個正整數Q(1<=Q<=100000),表示有Q組詢問。
接下來Q行,每行一個正整數k(1<=k<=100000)
Output
Q行,每行一個正整數,表示存在多少區間大於等於k。
Input示例
3
1 2 3
3
1
2
3
Output示例
6
5
3

思路:單調棧 處理處每一個數 作為最大值的區間 的左右端點
   題目要求的是 大於等於 k 的值
   統計數組後綴和
技術分享
 1
#include <cctype> 2 #include <cstdio> 3 4 typedef long long LL; 5 6 const int MAXN=100010; 7 8 int n,q; 9 10 int a[MAXN],stack[MAXN]; 11 12 LL ans[MAXN],pre[MAXN],nxt[MAXN]; 13 14 inline void read(int&x) { 15 int f=1;register char c=getchar(); 16 for(x=0
;!isdigit(c);c==-&&(f=-1),c=getchar()); 17 for(;isdigit(c);x=x*10+c-48,c=getchar()); 18 x=x*f; 19 } 20 21 int hh() { 22 read(n); 23 for(int i=1; i<=n; ++i) read(a[i]); 24 25 int top=0; 26 for(int i=1; i<=n; ++i) { 27 while(top && a[stack[top]] <= a[i]) --top; 28 if(!top) pre[i]=1; 29 else pre[i]=stack[top]+1; 30 stack[++top]=i; 31 } 32 33 top=0; 34 for(int i=n; i>=1; --i) { 35 while(top && a[stack[top]] < a[i]) --top; 36 if(!top) nxt[i]=n; 37 else nxt[i]=stack[top]-1; 38 stack[++top]=i; 39 } 40 41 for(int i=1; i<=n; ++i) ans[a[i]]+=(LL)(i-pre[i]+1)*(nxt[i]-i+1); 42 for(int i=100000; i>=1; --i) ans[i]+=ans[i+1]; 43 44 read(q); 45 int x; 46 while(q--) { 47 read(x); 48 printf("%lld\n",ans[x]); 49 } 50 51 return 0; 52 } 53 54 int sb=hh(); 55 int main(int argc,char**argv) {;}
代碼
 

51 Nod 1349 最大值