这个题目是一个典型的RMQ问题,给定一个整数序列,1~N,然后进行Q次询问,每次给定两个整数A,B,(1<=A<=B<=N),求给定的范围内,最大和最小值之差。
解法一:这个是最初的解法,时间上可能会超时,下面还有改进算法.4969ms
1 #include<stdio.h> 2 #include<stdlib.h> 3 #define INF 1000010 4 #define max(a,b) ((a)>(b)?(a):(b)) 5 #define min(a,b) ((a)>(b)?(b):(a)) 6 7 typedef struct res 8 { 9 int mx,mi; 10 } pair; 11 12 typedef struct node 13 { 14 struct node *lc,*rc; 15 int ld,rd; 16 pair res; 17 } node; 18 19 node *buildTree(int a,int b) 20 { 21 node*p=(node*)malloc(sizeof(node)); 22 p->ld=a; 23 p->rd=b; 24 p->res.mx=0; 25 p->res.mi=INF; 26 p->lc=p->rc=NULL; 27 if(a==b) 28 return p; 29 p->lc=buildTree(a,(a+b)>>1); 30 p->rc=buildTree(((a+b)>>1)+1,b); 31 return p; 32 } 33 34 void insert(node*T,int pos,int key) 35 { 36 int mid=(T->rd+T->ld)>>1; 37 if(T->rd==T->ld) 38 { 39 T->res.mx=T->res.mi=key; 40 return; 41 } 42 if(pos<=mid) 43 insert(T->lc,pos,key); 44 else insert(T->rc,pos,key); 45 T->res.mx=max(T->lc->res.mx,T->rc->res.mx); 46 T->res.mi=min(T->lc->res.mi,T->rc->res.mi); 47 return; 48 } 49 50 pair search(node*T,int a,int b) 51 { 52 pair temp1,temp2,ans; 53 int mid=(T->rd+T->ld)>>1; 54 55 temp1.mx=temp2.mx=0; 56 temp1.mi=temp2.mi=INF; 57 if(a<=T->ld&&T->rd<=b) 58 return T->res; 59 if(a<=mid) 60 temp1=search(T->lc,a,b); 61 if(b>mid) 62 temp2=search(T->rc,a,b); 63 ans.mx=max(temp1.mx,temp2.mx); 64 ans.mi=min(temp1.mi,temp2.mi); 65 return ans; 66 } 67 68 int main(void) 69 { 70 int n,q,i,a,b; 71 pair ans; 72 scanf("%d%d",&n,&q); 73 node *head=buildTree(1,n); 74 for(i=1; i<=n; i++) 75 { 76 scanf("%d",&a); 77 insert(head,i,a); 78 } 79 for(i=1; i<=q; i++) 80 { 81 scanf("%d%d",&a,&b); 82 ans=search(head,a,b); 83 printf("%d ",ans.mx-ans.mi); 84 } 85 return 0; 86 }
解法二:
利用数组的形式:3704ms
1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #define N 1000010 5 #define INF 1000010 6 #define max(a,b) ((a)>(b)?(a):(b)) 7 #define min(a,b) ((a)>(b)?(b):(a)) 8 9 int l[N],r[N],i,n; 10 typedef struct 11 { 12 int mx,mi; 13 } pair; 14 pair res[N]; 15 16 void BuildTree(int x,int y,int p) 17 { 18 l[p]=x; 19 r[p]=y; 20 if(x==y) 21 return; 22 BuildTree(x,(x+y)>>1,2*p); 23 BuildTree(((x+y)>>1)+1,y,2*p+1); 24 } 25 26 void Insert(int num,int p) 27 { 28 int mid=(l[p]+r[p])>>1; 29 res[p].mx=max(res[p].mx,num); 30 res[p].mi=min(res[p].mi,num); 31 if(l[p]==r[p]) 32 return; 33 if(i<=mid) 34 Insert(num,2*p); 35 else Insert(num,2*p+1); 36 } 37 38 pair search(int x,int y,int p) 39 { 40 pair a1,a2,ans; 41 a1.mx=a2.mx=0; 42 a1.mi=a2.mi=INF; 43 int mid=(l[p]+r[p])>>1; 44 if(x<=l[p]&&y>=r[p]) 45 return res[p]; 46 if(x<=mid) 47 a1=search(x,y,2*p); 48 if(y>mid) 49 a2=search(x,y,2*p+1); 50 ans.mx=max(a1.mx,a2.mx); 51 ans.mi=min(a1.mi,a2.mi); 52 return ans; 53 } 54 55 int main(void) 56 { 57 int q,j,x,y; 58 pair ans; 59 memset(res,0,sizeof(res)); 60 scanf("%d%d",&n,&q); 61 BuildTree(1,n,1); 62 for(i=0; i<N; i++) 63 res[i].mi=INF; 64 for(i=1; i<=n; i++) 65 { 66 scanf("%d",&j); 67 Insert(j,1); 68 } 69 70 for(i=0; i<q; i++) 71 { 72 scanf("%d%d",&x,&y); 73 ans=search(x,y,1); 74 printf("%d ",ans.mx-ans.mi); 75 } 76 return 0; 77 }
解法三:
这是利用别人的算法改进而来,所以有时候多借鉴别人的代码,并且可以和自己的想法结合起来,效果还不错.
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #define N 50010 5 #define INF 1000010 6 #define max(a,b) ((a)>(b)?(a):(b)) 7 #define min(a,b) ((a)>(b)?(b):(a)) 8 9 typedef struct 10 { 11 int l,r; 12 int mx,mi; 13 } pair; 14 pair temp[N*3]; 15 int Max,Min; 16 17 void BuildTree(int x,int y,int p) 18 { 19 temp[p].l=x; 20 temp[p].r=y; 21 temp[p].mx=0; 22 temp[p].mi=INF; 23 if(x==y) 24 return; 25 int mid=(x+y)/2; 26 BuildTree(x,mid,p*2); 27 BuildTree(mid+1,y,2*p+1); 28 } 29 30 void Insert(int v,int num,int p) 31 { 32 if(temp[v].l==temp[v].r) 33 { 34 temp[v].mx=temp[v].mi=num; 35 return ; 36 } 37 int mid=(temp[v].r+temp[v].l)/2; 38 if(p<=mid) 39 { 40 Insert(2*v,num,p); 41 temp[v].mx=max(temp[v].mx,temp[2*v].mx); 42 temp[v].mi=min(temp[v].mi,temp[2*v].mi); 43 } 44 else 45 { 46 Insert(2*v+1,num,p); 47 temp[v].mx=max(temp[v].mx,temp[2*v+1].mx); 48 temp[v].mi=min(temp[v].mi,temp[2*v+1].mi); 49 } 50 } 51 52 void search(int x,int y,int p) 53 { 54 if(temp[p].l==x&&temp[p].r==y) 55 { 56 Max=max(Max,temp[p].mx); 57 Min=min(Min,temp[p].mi); 58 return; 59 } 60 int mid=(temp[p].l+temp[p].r)/2; 61 if(x>mid) 62 { 63 search(x,y,2*p+1); 64 } 65 else if(y<=mid) 66 { 67 search(x,y,2*p); 68 } 69 else 70 { 71 search(x,mid,2*p); 72 search(mid+1,y,2*p+1); 73 } 74 return; 75 } 76 77 int main(void) 78 { 79 int n,q,i,x,y; 80 scanf("%d%d",&n,&q); 81 BuildTree(1,n,1); 82 for(i=1;i<=n;i++) 83 { 84 scanf("%d",&x); 85 Insert(1,x,i); 86 } 87 for(i=0;i<q;i++) 88 { 89 scanf("%d%d",&x,&y); 90 Max=0; 91 Min=INF; 92 search(x,y,1); 93 printf("%d ",Max-Min); 94 } 95 return 0; 96 }