UVa:11078 Open Credit System

来源:互联网 发布:广联达算量软件视频 编辑:程序博客网 时间:2024/05/17 03:13


这里我是用分治法做的。方法有点像算法导论上求最大连续数组和。


求Ai-Aj最大值。

有三种情况。

1.Ai Aj都位于左段区间

2.Ai Aj都位于右段区间

3.Ai位于左段区间,Aj位于右段区间。那么如果要使Ai-Aj最大,Ai肯定是左段区间的最大值,Aj是右段区间的最小值。

1和2都是原问题的更小规模,可以分治处理。3不是,我们可以把它视作合并的过程。


#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#define INF 1500000using namespace std;int A[100005];struct Num{    int a,b,s;    Num(){}    Num(int x,int y,int z):a(x),b(y),s(z){}};Num merge(int low,int mid,int high){    int L,R,max,min;    max=-INF;    for(int i=mid;i>=low;--i)    {        if(A[i]>=max)        {            max=A[i];            L=i;        }    }    min=INF;    for(int i=mid+1;i<=high;++i)    {        if(A[i]<=min)        {            min=A[i];            R=i;        }    }    return Num(L,R,A[L]-A[R]);}Num solve(int p,int q){    if(q==p)     return Num(p,q,-INF);    else    {        int mid=(p+q)/2;        Num x,m,y;        x=solve(p,mid);        y=solve(mid+1,q);        m=merge(p,mid,q);        if(x.s>=y.s&&x.s>=m.s) return x;        else if(m.s>=x.s&&m.s>=y.s) return m;        else return y;    }}int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        for(int i=0;i<n;++i) scanf("%d",&A[i]);        Num ans=solve(0,n-1);        printf("%d\n",ans.s);    }    return 0;}



先这样,明天再放上O(n)的做法。

---------------------------------------------------------------------------------------------------------

 

O(n)的算法。

边读边算速度会更快。

 

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;int A[100005];int main(){    int T;    scanf("%d",&T);    while(T--)    {        int n;        scanf("%d",&n);        for(int i=0; i<n; ++i) scanf("%d",&A[i]);        int ans=A[0]-A[1];        int MaxAi=A[0];        for(int j=1;j<n;++j)         {             ans=max(ans,MaxAi-A[j]);             MaxAi=max(A[j],MaxAi);         }         printf("%d\n",ans);    }    return 0;}


 

原创粉丝点击