1.最大数组和
注意:不是单次筛去的石头价值小,总的筛去的石头价值就一定最小,所以要比较总共筛去石头的价值
public class Main
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int t=scan.nextInt();
int []a=new int[200005];
long []b=new long[200005];
for(int i=0;i<t;i++)
{
int n=scan.nextInt();
int k=scan.nextInt();
long sum=0;
for(int j=1;j<=n;j++)
{
a[j]=scan.nextInt();
sum+=a[j];//先求出数组的总和
}
Arrays.sort(a,1,n+1);//先对数组进行排序
for(int j=1;j<=n;j++)
b[j]=b[j-1]+a[j];//排序后求前缀和,b[j]表示前j个数的和
long ans=0,back=0;
long mina=b[2*k];
for(int j=1;j<=k;j++)
{
back+=a[n-j+1];//用来统计最大的几个
ans=b[2*(k-j)]+back;
mina=Math.min(ans,mina);//从枚举的每一次中取最小值
}
System.out.println(sum-mina);//数组的总和减去要筛选掉的最小值的结果就是最大
}
scan.close();
}
}
2.大石头的搬运工
思路: 直接计算某点前后石头搬到当前位置的花费,然后比较出最小的花费
class stone//创建一个类,用来对石头的初始位置进行排序
{
int w;
int p;
public stone(int w,int p)
{
this.w=w;
this.p=p;
}
}
public class Main
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int n=scan.nextInt();//石头的数量
stone []a=new stone[100005];
for(int i=1;i<=n;i++)
{
int w=scan.nextInt();
int p=scan.nextInt();
a[i]=new stone(w, p);
}
Arrays.sort(a,1,n+1,((o1,o2)->o1.p-o2.p));//根据石头的位置排序,从小到大
long []front=new long[100005];
long []back=new long[100005];
front[1]=a[1].w;
back[n]=a[n].w;
//cost1和cost2分别表示前面石头和后面石头移动到当前位置的费用
long []cost1=new long[100005];
long []cost2=new long[100005];
//两个for循环分别计算将某点前面的石头和后面的石头搬到当前位置的花费
for(int i=2;i<=n;i++)
{
front[i]=front[i-1]+a[i].w;
cost1[i]=front[i-1]*(a[i].p-a[i-1].p)+cost1[i-1];
}
for(int i=n-1;i>=1;i--)
{
back[i]=back[i+1]+a[i].w;
cost2[i]=back[i+1]*(a[i+1].p-a[i].p)+cost2[i+1];
}
long ans=Long.MAX_VALUE;
for(int i=1;i<=n;i++)
{
//从所有点中找出花费最小的:
ans=Math.min(ans,cost1[i]+cost2[i]);
}
System.out.println(ans);
scan.close();
}
}
3.泡澡
一开始这么写的,果然运行超时了
class Shower
{
int s;
int t;
int p;
public Shower(int s,int t,int p)
{
this.s=s;//开始时间
this.t=t;//结束时间
this.p=p;//每分钟需要的热水量
}
}
public class Main
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int n=scan.nextInt();//洗澡的人数
int w=scan.nextInt();//热水器的容量
Shower []plan=new Shower[n+1];
int s,t,p;
int earliest=99999,latest=0;
for(int i=1;i<=n;i++)
{
s=scan.nextInt();
t=scan.nextInt();
p=scan.nextInt();
plan[i]=new Shower(s,t,p);
earliest=Math.min(earliest, s);
latest=Math.max(latest, t);
}
long sum=0;
for(int i=earliest;i<=latest;i++)
{
sum=0;
for(int j=1;j<=n;j++)
{
if(plan[j].s<=i&&i<=plan[j].t)
{
sum+=plan[j].p;
if(sum>w)
{
System.out.println("No");
break;
}
}
}
if(sum>w)
break;
}
scan.close();
}
}
要用差分数组
思路:加上原数组表示每分钟总共需要的热水,初始值都为0,可直接定义一个差分数组(初始值都为0),最后求前缀和得出原数组,遍历比较
注意:差分数组定义为int类型的话会有一个样例通不过。
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int n=scan.nextInt();//洗澡的人数
int w=scan.nextInt();//热水器的容量
int s,t,p;
int latest=0;
//原数组表示每分钟总共需要的热水,初始值都为0,所以可直接定义差分数组(初始值都为0)
long []a=new long[200005];//定义为int类型会有一个样例通不过
for(int i=1;i<=n;i++)
{
s=scan.nextInt();
t=scan.nextInt();
p=scan.nextInt();
//找出最晚结束的泡澡时间:
latest=Math.max(latest,t);
//对差分数组进行处理,题目给定区间是左闭右开,因此t表示区间右端点的后一位
a[s]+=p;
a[t]-=p;
}
for(int i=0;i<=latest;i++)
{
if(i!=0)//防止访问i=0时i-1=-1越界
a[i]+=a[i-1];//求前缀和还原数组
if(a[i]>w)
{
System.out.println("No");
break;
}
if(i==latest)//i为latest时所有人都已经结束,所以输出Yes
{
System.out.println("Yes");
}
}
scan.close();
}
4.肖恩的投球游戏
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
//在此输入您的代码...
int n=scan.nextInt();
int m=scan.nextInt();
int q=scan.nextInt();
int x1,y1,x2,y2,c;
int [][]a=new int[1005][1005];
int [][]diff=new int[1005][1005];
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
{
a[i][j]=scan.nextInt();
diff[i][j]=a[i][j]-a[i-1][j]-a[i][j-1]+a[i-1][j-1];
//求二维差分数组:diff[i][j]=a[i][j]-左-上+左上
}
for(int i=1;i<=q;i++)
{
x1=scan.nextInt();
y1=scan.nextInt();
x2=scan.nextInt();
y2=scan.nextInt();
c=scan.nextInt();
//处理二维差分数组:
diff[x1][y1]+=c;
diff[x1][y2+1]-=c;//右-c
diff[x2+1][y1]-=c;//下-c
diff[x2+1][y2+1]+=c;//右下+c
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
diff[i][j]+=diff[i-1][j]+diff[i][j-1]-diff[i-1][j-1];
//二维数组求前缀和+上+左-左上
System.out.print(diff[i][j]+" ");
}
System.out.println();
}
scan.close();
}