題目鏈接:http://poj.org/problem?id=3264
作者:kuangbin(轉載請注明出處,謝謝!!)
更多詳細文章,請訪問博客:www.cnblogs.com/kuangbin
ACM POJ 3264 Balanced Lineup
這到題目是線段樹的練習題目。
很簡單,練練手!!
AC程序:
/* POJ 3264 Balanced Lineup 題目意思:給定Q(1<=Q<=200000)個數A1,A2,```,AQ, 多次求任一區間Ai-Aj中最大數和最小數的差 */ #include<stdio.h> #include<algorithm> #include<iostream> using namespace std; #define MAXN 200005 #define INF 10000000 int nMax,nMin;//記錄最大最小值 struct Node { int l,r;//區間的左右端點 int nMin,nMax;//區間的最小值和最大值 }segTree[MAXN*3]; int a[MAXN]; void Build(int i,int l,int r)//在結點i上建立區間為(l,r) { segTree[i].l=l; segTree[i].r=r; if(l==r)//葉子結點 { segTree[i].nMin=segTree[i].nMax=a[l]; return; } int mid=(l+r)>>1; Build(i<<1,l,mid); Build(i<<1|1,mid+1,r); segTree[i].nMin=min(segTree[i<<1].nMin,segTree[i<<1|1].nMin); segTree[i].nMax=max(segTree[i<<1].nMax,segTree[i<<1|1].nMax); } void Query(int i,int l,int r)//查詢結點i上l-r的最大值和最小值 { if(segTree[i].nMax<=nMax&&segTree[i].nMin>=nMin) return; if(segTree[i].l==l&&segTree[i].r==r) { nMax=max(segTree[i].nMax,nMax); nMin=min(segTree[i].nMin,nMin); return; } int mid=(segTree[i].l+segTree[i].r)>>1; if(r<=mid) Query(i<<1,l,r); else if(l>mid) Query(i<<1|1,l,r); else { Query(i<<1,l,mid); Query(i<<1|1,mid+1,r); } } int main() { int n,q; int l,r; int i; while(scanf("%d%d",&n,&q)!=EOF) { for(i=1;i<=n;i++) scanf("%d",&a[i]); Build(1,1,n); for(i=1;i<=q;i++) { scanf("%d%d",&l,&r); nMax=-INF;nMin=INF; Query(1,l,r); printf("%d\n",nMax-nMin); } } return 0; }
另外附一參考程序:
#include <iostream> #include <algorithm> #include <numeric> using namespace std; #define MY_MIN 99999999 #define MY_MAX -99999999
struct CNode { int L,R; int nMin,nMax; CNode * pLeft, * pRight; }; int nMax, nMin; CNode Tree[1000000]; //CNode Tree[20]; int nCount = 0; void BuildTree(CNode * pRoot, int L,int R) { pRoot->L = L; pRoot->R = R; pRoot->nMin = MY_MIN; pRoot->nMax = MY_MAX;
if ( L != R) { nCount ++; pRoot->pLeft = Tree + nCount; nCount ++; pRoot->pRight = Tree + nCount; BuildTree( pRoot->pLeft, L, ( L + R )/2); BuildTree( pRoot->pRight, (L + R) / 2 + 1,R); } } void Insert( CNode * pRoot , int i,int v) { if( pRoot->L == i && pRoot->R == i ) { pRoot->nMin = pRoot->nMax = v; return; } pRoot->nMin = _cpp_min(pRoot->nMin,v); pRoot->nMax = _cpp_max(pRoot->nMax,v); if( i <= (pRoot->L + pRoot->R )/2 ) Insert( pRoot->pLeft,i,v); else Insert( pRoot->pRight,i,v); } void Query(CNode * pRoot, int s, int e) { if( pRoot->nMin >= nMin && pRoot->nMax <= nMax ) return; if( s == pRoot->L && e == pRoot->R) { nMin = _cpp_min(pRoot->nMin,nMin); nMax = _cpp_max(pRoot->nMax,nMax); return ; } if( e <= (pRoot->L + pRoot->R) / 2 ) Query(pRoot->pLeft, s,e); else if( s >= (pRoot->L + pRoot->R) / 2 + 1) Query(pRoot->pRight, s,e); else { Query(pRoot->pLeft, s,(pRoot->L + pRoot->R) / 2); Query(pRoot->pRight, (pRoot->L + pRoot->R) / 2 + 1 ,e); } } int main() { int n,q,h; int i,j,k; scanf("%d%d",&n,&q); nCount = 0; BuildTree(Tree,1,n); for( i = 1;i <= n;i ++ ) { scanf("%d",&h); Insert( Tree,i,h); } for( i = 0;i < q;i ++ ) { int s,e; scanf("%d%d", &s,&e); nMax = MY_MAX; nMin = MY_MIN; Query(Tree,s,e); printf("%d\n",nMax - nMin); } return 0; }
文章來源: http://www.cnblogs.com/kuangbin/archive/2011/08/14/2137862.html
|