版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/82718243
题目描述
有一个 m×n 的矩形木板。你需要把这个木板切成 1×1 的小方块,也就是竖着切 n-1 刀、横着切 m-1 刀。横着切第 i 个位置的权值为 xi ,竖着切第 j 个位置的权值为 yj 。切某一刀时的费用为切这一刀的权值乘上切过的块数。
请你安排切的顺序使得所有费用之和最小。
输入格式
第一行两个数 m,n 。
接下来一行 m-1 个整数 x1,x2,…,xm-1 。
接下来一行 n-1 个整数 y1,y2,…,yn-1 。
输出格式
输出一个数,表示最小的费用之和 mod 109 + 7 。
样例数据 1
输入
6 4
2 1 3 1 4
4 1 2
输出
42
备注
【数据规模与约定】
对于 30% 的数据, m + n≤10 。
对于 60% 的数据, m,n≤500 。
对于 100% 的数据, 2≤m,n≤106 ;0≤xi,yj≤109 。
【提醒】
建议本题加读入优化。
分析
又是一道水题。。。
我们很容易发现每次都选择权值最大的位置割,最后结果才会是最优
又因为如果都是横着或竖着切,其顺序不影响最后的费用,我们就可以对 x 和 y 分别进行排序,然后用两个指针搞一搞,就over了
又傻逼了的我,想着节约时间,就把相同的权值的统计在一起,然后处理不得当,100分哗哗啦啦的变成20分,呜呜呜呜,下次考试一定要多造数据
代码
注释掉的地方就是考场上写的部分,来组数据有兴趣的同学模拟感受一下我的傻逼:
6 6
4 3 2 1 1
6 5 4
#include<bits/stdc++.h>
#define in read()
#define P 1000000007
#define N 1000009
#define ll long long
using namespace std;
inline int read(){
char ch;int res=0;
while((ch=getchar())<'0'||ch>'9');
while(ch>='0'&&ch<='9'){
res=(res<<3)+(res<<1)+ch-'0';
ch=getchar();
}
return res;
}
int n,m,x[N],y[N];
int main(){
n=in;m=in;
int i,j,k;
for(i=1;i<n;++i) x[i]=in;
for(i=1;i<m;++i) y[i]=in;
sort(x+1,x+n);sort(y+1,y+m);
int heng=0,zong=0;
ll sum=0;
i=n-1;j=m-1;x[0]=-1;y[0]=-1;
while(i&&j){
/*int tx=1,ty=1;
while(x[i-1]==x[i]) i--,tx++;
while(y[j-1]==y[j]) j--,ty++;*/
if(x[i]==y[j]){
sum=(sum+1ll*x[i]*(zong+1))%P;
heng++;
sum=(sum+1ll*y[j]*(heng+1))%P;
zong++;
i--;j--;
}
else{
if(x[i]>y[j]){
sum=(sum+1ll*x[i]*(zong+1))%P;
heng++;
i--;
}
else {
sum=(sum+1ll*y[j]*(heng+1))%P;
zong++;
j--;
}
}
}
if(!i){
for(int q=j;q>=1;--q)
sum=(sum+1ll*y[q]*(heng+1))%P;
}
if(!j){
for(int q=i;q>=1;--q)
sum=(sum+1ll*x[q]*(zong+1))%P;
}
cout<<sum;
return 0;
}
不要问我为什么又没有第三题,因为……pdf 4 篇的代码,我实在不想敲