给出 n 个数的序列,先把每个数逆序(如 120 变为 21,123 变为 321),将会产生 n 个新数,我们把它称作序列 A。
分治递归解法:
之后对序列 A 中的 n-1 个数进行 q 次操作,每次操作将会把序列 A 上的某个数替换成另一个数,并询问序列 A 中任取连续的一段数,如何取才能使这段数的和最大,请你输出最大值。
Input
输入数据有多组(数据组数不超过 100)。
对于每组数据:
- 第一行输入 n, q (1 <= n <= 10000, 1 <= q <= 100) 分别表示数字个数和操作次数
- 接下来的一行输入 n 个正整数,最大不超过 10000
- 接下来的 q 行,每行输入 2 个整数,分别为要替换的数的位置 xi (1 <= xi <= n) 和要修改的值 yi (-10000 <= yi <= 10000)
当 n = 0 时输入结束。
Output
对于每组数据第一行输出 "Case #x:" (不包括引号,冒号后无空格),x 表示当前为第几组数据。之后对应 q 次操作每次操作输出一行,表示查询的答案。
Example Input
5 2 1 2 3 4 5 2 -5 2 5 3 3 45 12 32 3 -5 1 5 2 10 0
Example Output
Case #1: 12 18 Case #2: 75 26 15
这道题是我们专业的期末考试上机题,当时时间比较紧张,只有一位大佬做了出来。我当时读完这道题时就知道是动归,所以就果断放弃了...
到最后回首才发现... 这道题似曾相识... 原来寒假的时候遇到过最大子序列和的问题,当时还知道两种方法,分治递归和动归,只不过这里就是变化了一下,把每个数字翻转一下,所以,就是多写个函数的问题...
动归解法:
#include <stdio.h>
#include <stdlib.h>
#define N 10010
int a[N];
int maxsum(int length)
{
int i,sum=0,max=0;
for(i=0;i<length;i++)
{
sum+=a[i];
if(sum<0)
sum=0;
else if(sum>max)
max=sum;
}
return max;
}
int f(int n)
{
int s[6];
int i,x=0;
while(n!=0)
{
s[x++]=n%10;
n/=10;
}
for(i=0;i<x;i++)
{
n=n*10+s[i];
}
return n;
}
int main()
{
int n,q,x,y;
int i,t=0;
while(~scanf("%d",&n)&&n!=0)
{
scanf("%d",&q);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
a[i]=f(a[i]);
}
printf("Case #%d:\n",++t);
while(q--)
{
scanf("%d%d",&x,&y);
a[x-1]=y;
printf("%d\n",maxsum(n));
}
}
return 0;
}
分治递归解法:
#include <stdio.h>
#include <stdlib.h>
#define N 10010
int a[N];
int maxsum(int left,int right)
{
int sum,i;
if(left==right)
return a[left];
int mid=(left+right)/2;
int leftsum=maxsum(left,mid);
int rightsum=maxsum(mid+1,right);
int lefts=0,sum1=0;
for(i=mid;i>=left;i--)
{
lefts+=a[i];
if(lefts>sum1)
sum1=lefts;
}
int rights=0,sum2=0;
for(i=mid+1;i<=right;i++)
{
rights+=a[i];
if(rights>sum2)
sum2=rights;
}
sum=leftsum>rightsum?leftsum:rightsum;
sum=sum>(sum1+sum2)?sum:(sum1+sum2);
return sum;
}
int f(int n)
{
int s[6];
int i,x=0;
while(n!=0)
{
s[x++]=n%10;
n/=10;
}
for(i=0;i<x;i++)
{
n=n*10+s[i];
}
return n;
}
int main()
{
int n,q,x,y;
int i,t=0;
while(~scanf("%d",&n)&&n!=0)
{
scanf("%d",&q);
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
a[i]=f(a[i]);
}
printf("Case #%d:\n",++t);
while(q--)
{
scanf("%d%d",&x,&y);
a[x-1]=y;
printf("%d\n",maxsum(0,n-1));
}
}
return 0;
}