目录
B - 删数问题
键盘输入一个高精度的正整数 nn,去掉其中任意 kk 个数字后剩下的数字按原左右次序将组成一个新的正整数。编程对给定的 n,kn,k,寻找一种方案使得剩下的数字组成的新数最小。
输出应包括所去掉的数字的位置和组成的新的整数。
输入格式
第一行一个高精度整数 nn,nn 不超过 200200 位。
第二行一个整数 kk,kk 小于 nn 的位数,表示要删去的数字个数。
输出格式
一个合法的整数,表示最后剩下的最小数。
Sample 1
Inputcopy | Outputcopy |
---|---|
175438 4 | 13 |
Sample 2
Inputcopy | Outputcopy |
---|---|
101 2 | 0 |
思路:我们每次只需要删除第一个开始下降的数即可,如果所有位数上的数都是单调递增,那么就删除最后一位数即可。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
String s=cin.next();
int k=cin.nextInt();
StringBuffer sb=new StringBuffer(s);
while(k-->0) {
int x=-1;
for(int i=0;i<sb.length()-1;i++) {
if(sb.charAt(i)>sb.charAt(i+1)) {
x=i;
sb.deleteCharAt(i);
break;
}
}
if(x==-1)sb.deleteCharAt(sb.length()-1);
// System.out.println(sb.length());
}
// System.out.println(sb.toString());
String ss=sb.toString().replaceAll("^0*", "");
if(ss.length()==0)System.out.println(0);
else {
System.out.println(ss);
}
}
}
C - 股票买卖
最近越来越多的人都投身股市,阿福也有点心动了。谨记着“股市有风险,入市需谨慎”,阿福决定先来研究一下简化版的股票买卖问题。
假设阿福已经准确预测出了某只股票在未来 N 天的价格,他希望买卖两次,使得获得的利润最高。为了计算简单起见,利润的计算方式为卖出的价格减去买入的价格。
同一天可以进行多次买卖。但是在第一次买入之后,必须要先卖出,然后才可以第二次买入。
现在,阿福想知道他最多可以获得多少利润。
Input
输入的第一行是一个整数 T (T <= 50) ,表示一共有 T 组数据。
接下来的每组数据,第一行是一个整数 N (1 <= N <= 100, 000) ,表示一共有 N 天。第二行是 N 个被空格分开的整数,表示每天该股票的价格。该股票每天的价格的绝对值均不会超过 1,000,000 。
Output
对于每组数据,输出一行。该行包含一个整数,表示阿福能够获得的最大的利润。
Sample
Inputcopy | Outputcopy |
---|---|
3 7 5 14 -2 4 9 3 17 6 6 8 7 4 1 -2 4 18 9 5 2 | 28 2 0 |
Hint
对于第一组样例,阿福可以第 1 次在第 1 天买入(价格为 5 ),然后在第 2 天卖出(价格为 14 )。第 2 次在第 3 天买入(价格为 -2 ),然后在第 7 天卖出(价格为 17 )。一共获得的利润是 (14 - 5) + (17 - (-2)) = 28
对于第二组样例,阿福可以第 1 次在第 1 天买入(价格为 6 ),然后在第 2 天卖出(价格为 8 )。第 2 次仍然在第 2 天买入,然后在第 2 天卖出。一共获得的利润是 8 - 6 = 2
对于第三组样例,由于价格一直在下跌,阿福可以随便选择一天买入之后迅速卖出。获得的最大利润为 0
思路:根据题意可知,我们需要在n天内找到两次买入售出的最大利润,并且在第一次出售之后才能进行第二次的操作,那么我们便可以从两端开始向中间聚拢, 然后我们便可以使用动态规划进行动态的处理,最后遍历求得f[i]+g[i]的最大值即可
#include<bits/stdc++.h>
using namespace std;
const int N=100010;
int f[N]; //动态表示在第i天之前购买并出售的最大利润
int g[N];//动态表示在第i-n天内购买并出售的最大值利润
int a[N];
int main(){
int t,n;
scanf("%d",&t);
while(t--){
//一定要初始化数组,防止上一数据对本数据造成干扰
memset(f,-1,sizeof(f));
memset(g,-1,sizeof(g));
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
int ma=-1e9,mi=1e9;
for(int i=1;i<=n;i++){
mi=min(mi,a[i]);
f[i]=max(f[i-1],a[i]-mi);
}
for(int i=n;i>0;i--){
ma=max(ma,a[i]);
g[i]=max(g[i+1],ma-a[i]);
}
int maxn=0;
for(int i=1;i<=n;i++){
maxn=max(maxn,f[i]+g[i]);
}
printf("%d\n",maxn);
}
return 0;
}
import java.io.*;
import java.util.*;
public class Main {
//快输模板
static class FastScanner{//用于快速读入大量数据
BufferedReader br;
StringTokenizer st;
public FastScanner(InputStream in) {
br = new BufferedReader(new InputStreamReader(in),16384);
eat("");
}
public void eat(String s) {
st = new StringTokenizer(s);
}
public String nextLine() {
try {
return br.readLine();
} catch (IOException e) {
return null;
}
}
public boolean hasNext() {
while(!st.hasMoreTokens()) {
String s = nextLine();
if(s==null) return false;
eat(s);
}
return true;
}
public String next() {
hasNext();
return st.nextToken();
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
}
static FastScanner cin = new FastScanner(System.in);//快读
static PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
//核心代码
static int N=100010;
static int f[]=new int[N+1];//动态表示在第i天之前购买并出售的最大利润
static int g[]=new int[N+1];//动态表示在第i-n天内购买并出售的最大值利润
public static void main(String[] args) {
// TODO Auto-generated method stub
int t=cin.nextInt();
while(t-->0) {
int n=cin.nextInt();
int a[]=new int[n+1];
//一定要初始化数组,防止上一数据对本数据造成干扰
Arrays.fill(f,0);
Arrays.fill(g,0);
for(int i=1;i<=n;i++)a[i]=cin.nextInt();
int min=Integer.MAX_VALUE,max=Integer.MIN_VALUE;
for(int i=1;i<=n;i++) {
min=Math.min(min,a[i]);
f[i]=Math.max(a[i]-min, f[i-1]);
}
max=a[n];
for(int i=n-1;i>0;i--) {
max=Math.max(max, a[i]);
g[i]=Math.max(g[i+1],max-a[i]);
}
int ans=0;
for(int i=1;i<=n;i++) {
ans=Math.max(ans, f[i]+g[i]);
}
out.println(ans);
out.flush();
}
}
}
D - 数列分段
题目描述
对于给定的一个长度为 NN 的正整数数列 Ai,现要将其分成连续的若干段,并且每段和不超过 M(可以等于 M),问最少能将其分成多少段使得满足要求。
输入格式
第一行包含两个正整数 N,M,表示了数列 A_iAi 的长度与每段和的最大值;
第二行包含 N 个空格隔开的非负整数 A_iAi。
输出格式
输出文件仅包含一个正整数,输出最少划分的段数。
样例
Inputcopy | Outputcopy |
---|---|
5 6 4 2 4 5 1 | 3 |
数据范围与提示
对于 20\%20% 的数据,有N\le 10N≤10;
对于 40\%40% 的数据,有N\le 1000N≤1000;
对于 100\%100% 的数据,有 N\le 10^5, M\le 10^9N≤105,M≤109,MM 大于所有数的最大值。
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin=new Scanner(System.in);
int n=cin.nextInt();
int m=cin.nextInt();
int cnt=1,sum=0;
for(int i=0;i<n;i++) {
int x=cin.nextInt();
sum+=x;
if(sum>m) {
sum=x;cnt++;
}
}
System.out.println(cnt);
}
}