埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A-Wasserstein Distance
链接:https://www.nowcoder.com/acm/contest/91/A
来源:牛客网
题目描述
最近对抗生成网络(GAN)很火,其中有一种变体WGAN,引入了一种新的距离来提高生成图片的质量。这个距离就是Wasserstein距离,又名铲土距离。
这个问题可以描述如下:
有两堆泥土,每一堆有n个位置,标号从1~n。第一堆泥土的第i个位置有ai克泥土,第二堆泥土的第i个位置有bi克泥土。小埃可以在第一堆泥土中任意移挪动泥土,具体地从第i个位置移动k克泥土到第j个位置,但是会消耗的体力。小埃的最终目的是通过在第一堆中挪动泥土,使得第一堆泥土最终的形态和第二堆相同,也就是ai=bi (1<=i<=n), 但是要求所花费的体力最小
左图为第一堆泥土的初始形态,右图为第二堆泥土的初始形态,颜色代表了一种可行的移动方案,使得第一堆泥土的形态变成第二堆泥土的形态
输入描述:
输入测试组数T,每组测试数据,第一行输入n,1<=n<=100000,紧接着输入两行,每行n个整数,前一行为a1, a2,…,an,后一行为b1,b2,…,bn.其中0<=ai,bi<=100000,1<=i<=n,数据保证
输出描述:
对于每组数据,输出一行,将a土堆的形态变成b土堆的形态所需要花费的最小体力
示例1
输入
2
3
0 0 9
0 2 7
3
1 7 6
6 6 2
输出
2
9
备注:
输入数据量较大,建议使用scanf/printf
思路
一开始把问题想得复杂了。。求了一个差值数组,然后两个“指针”游走于这个差值数组间计算 “移动距离 & 挪动的泥土数”。
看别人提交的代码,逻辑上其实可以简化到:
ans[i]+=abs(a[i]-b[i]);
a[i+1]+=a[i]-b[i];
emmm。。。给跪了。。。
然后备注里面的“输入数据量较大,建议使用scanf/printf”,用 cin/cout 的话,加上
ios::sync_with_stdio(false);
cin.tie(0);
也是可以过滴O(∩_∩)O哈哈~
关于这两个语句的含义:
cin,cout之所以“效率低”,是因为先把要输出的东西存入缓冲区,再输出,导致效率降低,而ios::sync_with_stdio(false);可以取消iostream的输入输出缓存,可以节省许多时间,使效率与scanf与printf相差无几。
在默认的情况下cin绑定的是cout,每次执行 << 操作符的时候都要调用 flush,这样会增加IO负担。可以通过cin.tie(0);(0表示NULL)来解除cin与cout的绑定,进一步加快执行效率。
AC代码
#include <iostream>
#include <vector>
#include <iomanip>
typedef long long ll;
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin >> T;
while(T--) {
vector<ll> veca,vecb;
int n;
cin >> n;
for(int i=0; i<n; i++) {
ll a;
cin >> a;
veca.push_back(a);
}
for(int i=0; i<n; i++) {
ll b;
cin >> b;
vecb.push_back(b);
}
vector<ll> difference; // 差值数组
for(int i=0; i<n; i++) {
ll chai=veca[i]-vecb[i];
difference.push_back(chai);
}
ll ans=0;
for(int i=0; i<n-1; i++) {
ans+=abs(difference[i]);
difference[i+1]+=difference[i];
}
cout << ans << endl;
}
return 0;
}