A
Time Limit:10000MS Memory Limit:65536K
Total Submit:94 Accepted:32
Description
有n(1<=n<=100000)個數a1,a2,a3,…,an-1,an(-100000<=ai<=100000), 對於m次(1<=m<=100000)as到at區間的詢問,求該區間的任意兩個數差值的最大值。
Input
輸入由多組資料群組成。每組資料,第1行輸入一個數n;第2行輸入n個整數,每個數後用空格隔開,分別表示a1,a2,……,an-1,an;第3行輸入一個m。第4到m+3行,每行輸入兩個整數s和t(1<=s<=t<=n),表示要查詢的區間為as到at。
Output
對於每個查詢輸出一行,表示該區間內任意兩個數差值的最大值。
Sample Input
510 3 -2 5 -931 52 43 331 3 -531 32 31 2
Sample Output
1970882
看到這道題目,像我們這些水手肯定以一般的思路,先建立數組然後然後在要求的數組範圍內全部遍曆一邊,但仔細看看這道題目,這道題目
的限制時間長達10S,時間越多越覺得平常思路不可行,但心裡還是不放心,先嘗試著普通思路做了一遍,很高興的TLE,於是,我問了幾位了
A了的高手們,一位小牛說m才100000;只要運行m*00就不會超,於是有種方法把100000分位以300個數為一個集體的,在每個集體
中記錄最大值和最小值;這樣一來,如果要求首位之間的兩個數之間絕對值最大的就只要遍曆100000/300,所以時間當然OK了,方法也肯巧妙
,時間複雜度也才(m*m/300);但比起線段樹的(m*logm)還是慢了很多,但這題的話可能找最大值最小值找了好幾次,所以時間也不
見得少了很多;
線段樹是在2分分治的基礎上的,它的好處一開始先是作預先處理,然後在進行更新;然後在統計;
具體怎麼樣我也還不怎麼懂,再去做做這類題鞏固鞏固!
My Code如下:
#include<stdio.h>
#define Max(a,b) a > b ? a : b
#define Min(a,b) a > b ? b : a
struct tree
{
int left;
int right;
int mid;
int max,min;
}seg_tree[500000];
void maketree(int l,int r,int num)
{
seg_tree[num].left=l;
seg_tree[num].right=r;
seg_tree[num].mid=(l+r)/2;
seg_tree[num].max=-100000;
seg_tree[num].min=100000;
if(l+1!=r)
{
maketree(l,seg_tree[num].mid,2*num);
maketree(seg_tree[num].mid,r,2*num+1);
}
return ;
}
void insertseg(int i,int value,int num)
{
if(seg_tree[num].max<value)
seg_tree[num].max=value;
if(seg_tree[num].min>value)
seg_tree[num].min=value;
if(seg_tree[num].left+1!=seg_tree[num].right)
{
if(i<seg_tree[num].mid)
insertseg(i,value,2*num);
else insertseg(i,value,2*num+1);
}
return ;
}
int findmax(int l,int r,int num)
{
int x,y;
if(l==seg_tree[num].left&&r==seg_tree[num].right)
return seg_tree[num].max;
if(r<=seg_tree[num].mid)
return findmax(l,r,num*2);
if(l>=seg_tree[num].mid)
return findmax(l,r,num*2+1);
else
//return Max(findmax(l,seg_tree[num].mid,num*2),findmax(seg_tree[num].mid,r,num*2+1));
{
x = findmax(l,seg_tree[num].mid,num*2);
y = findmax(seg_tree[num].mid,r,num*2+1);
return Max(x,y);
}
}
int findmin(int l,int r,int num)
{
int x,y;
if(l==seg_tree[num].left&&r==seg_tree[num].right)
return seg_tree[num].min;
if(r<=seg_tree[num].mid)
return findmin(l,r,num*2);
if(l>=seg_tree[num].mid)
return findmin(l,r,num*2+1);
else
//return Min(findmin(l,seg_tree[num].mid,num*2),findmin(seg_tree[num].mid,r,num*2+1));
{
x = findmin(l,seg_tree[num].mid,num*2);
y = findmin(seg_tree[num].mid,r,num*2+1);
return Min(x,y);
}
}
int main()
{
int n,i,m;
int temp,start,end;
while(scanf("%d",&n)!=EOF)
{
maketree(1,n+1,1);
for(i=1;i<=n;i++)
{
scanf("%d",&temp);
insertseg(i,temp,1);
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&start,&end);
printf("%d/n",findmax(start,end+1,1)-findmin(start,end+1,1));
}
}
return 0;
}
有大牛更好的代碼麻煩留下!!謝謝