标签:
题目,给定n个时钟,要求把他们调成一样的时间。求最小的步数
思路:肯定是有一个时钟作为标准的啦,要找到这个时钟,怎么找呢?没其他方便的方法,暴力枚举。那么枚举后,怎么能快速地算到其他时钟转到这个时钟的时间呢?首先,如果我们把时间转换成数字,那应该好做点。现在问题是给定n个数,枚举最小的步数,使得n个数字相同。
例如我们把时间变为1、3、5、7、9这样的。(输出的时候按照权值变化成时间就可以了)
现在枚举5,预处理一个前缀和sum[i],那么在5前面的数字一共变化步可以快速算出来。i*a[i]-sum[i]
后面的,因为不能降下来,只能增加。7变5需要+8 其实也就是10-(7-5)了。所以后半部分的值是(n-i)*10 - (sum[n]-sum[i]-(n-i)*a[i]);
所以可以O(n)解决。利用了前缀和
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 1e5+20; LL a[maxn]; const LL hh = 1e12; const LL mm = 1e6; LL sum[maxn]; void work () { int n; cin>>n; for (int i=1;i<=n;++i) { LL u,v,w; cin>>u>>v>>w; a[i]=u*hh+v*mm+w; } sort(a+1,a+1+n); for (int i=1;i<=n;++i) { sum[i] = sum[i-1] + a[i]; } LL ans=-1; for (int i=1;i<=n;++i) { LL t = i*a[i]-sum[i]; t += (n-i)*hh*12 - (sum[n]-sum[i] - ((n-i)*a[i])); if (ans==-1) ans=t; else ans=min(ans,t); //cout<<t<<" "<<i<<endl; } LL t = ans/hh; ans -= t*hh; LL t1 = ans/mm; ans -= t1*mm; cout<<t<<" "<<t1<<" "<<ans<<endl; return ; } int main() { #ifdef local freopen("data.txt","r",stdin); #endif work(); return 0; }
标签:
原文地址:http://www.cnblogs.com/liuweimingcprogram/p/5766622.html