hdu 1505 hdu 1506 hdu 2870 综合解答

1505,1506一类题,1505套用1506即可

就像最大子阵和与最大连续子和的关系

回顾最大连续子序列

状态方程:sum[i]=max(sum[i-1]+a[i],a[i]);最后从头到尾扫一边

Sum[i]为以i结尾的最大连续子和

    也可以写成:

                Max=a[0];

                Current=0;

                for(i=0;i<n;i++)

                {

                    if(Current<0)

                        Current=a[i];

                    else

                        Current+=a[i];

                    if(Current>Max)

                        Max=Current;

                }

最大子矩阵记录方式做一些处理就可以直接用最大连续子序列的做法

       for(i=1;i<=n;i++)

          for(j=1;j<=n;j++)

          {

              scanf("%d",&t);

              a[i][j]=a[i-1][j]+t;

          }

a[i][j]表示第1行到第i行第j列的和…草,反正我能想明白,不解释。

对每一行都可以用最大子序列之和。

 

回到这个题,其实效率高在left right 数组

Left[i]=t,表示v[t],v[t+1]…v[i]均满足>=v[i],下面的循环就能理解了

以及从中间往两边搜的思想

//hdu 1506
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define N 100005
long long max,ae,a[N],left[N],right[N];
int i,n,k;

int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(!n)break;
        max=0;
        for(i=0;i<n;i++)
        {
            scanf("%I64d",&a[i]);
        }
        left[0]=0;
        right[n-1]=n-1;
        for(i=1;i<n;i++)
        {
            k=i;
            while(k>=1&&a[i]<=a[k-1])k=left[k-1];
            left[i]=k;
        }
        for(i=n-2;i>=0;i--)
        {
            k=i;
            while(k<=n-2&&a[i]<=a[k+1])k=right[k+1];
            right[i]=k;
        }
        for(i=0;i<n;i++)
        {
            ae=(right[i]-left[i]+1)*a[i];
            max=max>ae?max:ae;
        }
        printf("%I64d\n",max);
    }

    return 0;
}


//hdu 1505
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define N 1005

int map[N][N];
long long left[N],right[N],a[N],ae,max;/*left[i]=j存的是从a[j]到a[i]都满足>=a[i],
故当a[i]>=a[k],必有至少从j到k都有>=a[k],这才是效率高的地方*/

int main()
{
    //freopen("in.in","r",stdin);
    //freopen("out.out","w",stdout);
    int i,j,k,m,n,k1,j1;
    char c;

    scanf("%d",&k1);
    while(k1--)
    {
        scanf("%d%d",&m,&n);
        memset(map,0,sizeof(map));
        max=0;
        for(i=0;i<m;i++)
        {
            for(j=0;j<n;j++)
            {
                scanf("%c",&c);
                if(c==' '||c=='\n'||c=='\0')j--;
                if(c=='R'){map[i][j]=0;continue;}
                if(i==0&&c=='F'){map[0][j]=1;continue;}
                if(c=='F')map[i][j]=map[(i-1)][j]+1;
            }
            /*每行求和*/
            left[0]=0;
            right[n-1]=n-1;
            for(j=1;j<n;j++)
            {
                k=j;
                while(k>0&&map[i][j]<=map[i][k-1]&&map[i][j])k=left[k-1];
                left[j]=k;
            }
            for(j=n-2;j>=0;j--)
            {
                k=j;
                while(k<n-1&&map[i][j]<=map[i][k+1]&&map[i][j])k=right[k+1];
                right[j]=k;
            }
            for(j=0;j<n;j++)
            {
                ae=(right[j]-left[j]+1)*map[i][j];
                max=max>ae?max:ae;
            }
        }
        printf("%lld\n",max*3);
    }

    return 0;
}

又一道类型题与hdu1505  hdu 1506 相似

只是多了一步,把字母全部尽量变成a或b或c

套用hdu1505

//hdu2870

#include<cstdio>
#include<cstring>
using namespace std;
#define Max(a,b) (a)>(b)?(a):(b)
#define N 1005

char map[N][N],m[N][N];
int left[N],right[N],num[N][N],m1,n;

int solve(char test)
{
    int i,j,k,s;
    memset(num,0,sizeof(num));
    for(j=0;j<m1;j++)
        if(m[0][j]==test)num[0][j]=1;
    for(i=1;i<n;i++)
        for(j=0;j<m1;j++)
        {
           if(m[i][j]==test&&m[i-1][j]==test)
                num[i][j]=num[i-1][j]+1;
           else
           if(m[i][j]==test)num[i][j]=1;
           else
           num[i][j]=0;
        }
    s=0;

    for(i=0;i<n;i++)
    {
        left[0]=0;
        right[m1-1]=m1-1;
        for(j=1;j<m1;j++)
        {
            k=j;
            while(k-1>=0&&num[i][k-1]>=num[i][j])k=left[k-1];
            left[j]=k;
        }
        for(j=m1-2;j>=0;j--)
        {
            k=j;
            while(k+1<m1&&num[i][k+1]>=num[i][j])k=right[k+1];
            right[j]=k;
        }
        for(j=0;j<m1;j++)
            s=Max(s,(right[j]-left[j]+1)*num[i][j]);
    }
    return s;
}

int main()
{

    char c;
    int i,j,max;

    while(scanf("%d%d",&n,&m1)!=EOF)
    {
        max=0;
        memset(map,0,sizeof(map));
        memset(m,0,sizeof(m));
        for(i=0;i<n;i++)
            for(j=0;j<m1;j++)
            {
                scanf("%c",&c);
                if(c=='\n'||c==' '||c=='\0')j--;
                else map[i][j]=m[i][j]=c;
            }
        for(i=0;i<n;i++)
            for(j=0;j<m1;j++)
                if(map[i][j]=='w'||map[i][j]=='y'||map[i][j]=='z')m[i][j]='a';
        max=Max(max,solve('a'));
        for(i=0;i<n;i++)
            for(j=0;j<m1;j++)
                if(map[i][j]=='w'||map[i][j]=='x'||map[i][j]=='z')m[i][j]='b';
                else m[i][j]=map[i][j];
        max=Max(max,solve('b'));
        for(i=0;i<n;i++)
            for(j=0;j<m1;j++)
                if(map[i][j]=='x'||map[i][j]=='y'||map[i][j]=='z')m[i][j]='c';
                else m[i][j]=map[i][j];
        max=Max(max,solve('c'));

        printf("%d\n",max);
    }

    return 0;
}


你可能感兴趣的:(hdu 1505 hdu 1506 hdu 2870 综合解答)