Problem Description
MLE 得到了 QAQ 的真传,但 QAQ 为了检验 MLE 智商是否可以真正领悟,于是出了这一道题:给出 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> int f(int x) { int i , b[6],top = 0; while(x!=0) { b[top] = x%10; top++; x /=10; } x = 0; for(i = 0;i<top;i++) x = x*10+b[i]; return x; } int main() { int n ,i ,q,a[100010],b[100010],max,x,y,cas =1; while(scanf("%d",&n)!=EOF&&n!=0) { scanf("%d",&q); for(i = 0;i<n;i++) { scanf("%d",&a[i]); a[i] = f(a[i]); } printf("Case #%d:\n",cas); while(q--) { scanf("%d %d",&x,&y); a[x-1] = y; b[0] = a[0]; max = b[0]; for(i = 1;i<n;i++) { if(b[i-1]>0) { b[i] = b[i-1]+a[i]; } else { b[i] = a[i]; } if(b[i]>max) max = b[i]; } printf("%d\n",max); } cas++; } return 0; }
分治递归
第一种情况:a[1...n]的最大子段和和a[1...n/2]最大子段和相同
第二种情况:a[1...n]的最大子段和和a[n/2+1...n]最大子段和相同
第三种情况:a[1...n]的最大子段和是a[i....j]任意一段和 1<=i<= n/2 , n/2+1 <=j<= n 较复杂
#include<stdio.h> #define max 100010 int a[max]; int maxsub(int left,int right) { int mid, i; int sum,left_sum,right_sum; int left_max,right_max; mid = (left+right)/2; if(left==right) { return a[left]>0?a[left]:0; } else { left_sum = maxsub(left,mid); right_sum = maxsub(mid+1,right); sum = 0; left_max = 0; for(i = mid;i>=left;i--) { sum+=a[i]; if(sum>left_max) { left_max = sum; } } sum = 0; right_max = 0; for(i = mid+1;i<=right;i++) { sum+=a[i]; if(sum>right_max) { right_max = sum; } } sum = right_max+left_max; if(sum<left_sum) sum = left_sum; if(sum<right_sum) sum = right_sum; } return sum; } int f(int x) { int i ,b[6],top; while(x!=0) { b[top] = x%10; top++; x/=10; } x = 0; for(i = 0;i<top;i++) { x = x*10+b[i]; } return x; } int main() { int n ,i , q ,x ,y ,cas = 1; while(scanf("%d",&n)!=EOF&&n!=0) { scanf("%d",&q); for(i =0 ;i<n;i++) { scanf("%d",&a[i]); a[i] = f(a[i]); } printf("Case #%d:\n",cas); while(q--) { scanf("%d %d",&x,&y); a[x-1] = y; printf("%d\n",maxsub(0,n-1)); } cas++; } return 0; }