Codeforces Round #248 (Div. 2) C - Ryouko's Memory Note
3568 ワード
に言及
1冊の本にはnページある.次はm個の知識点を探して、それぞれs[1]s[2]....s[m]ページにあります.あるページの知識点をすべて別のページに移動する機会があります.最も少ないページをめくる回数を求めます.
例えばs[1]s[2]....s[m]のページめくり回数は|s[1]-s[2]|+|s[2]-s[3]|+...+|s[m-1]-s[m]|
構想
各ページ番号がシーケンスの前後に現れるページ番号(例えば1 2 3 2 4では2前後に1 3 3 4が現れたことがある)を記録し(隣接するページ番号が同じであれば構わないことに注意)、それらの中位数を取ると、必ずこのページ番号を移動する最適解がある.すべてのページ番号を一度遍歴して、全体の最適解を取ればいいです.
コード#コード#
1冊の本にはnページある.次はm個の知識点を探して、それぞれs[1]s[2]....s[m]ページにあります.あるページの知識点をすべて別のページに移動する機会があります.最も少ないページをめくる回数を求めます.
例えばs[1]s[2]....s[m]のページめくり回数は|s[1]-s[2]|+|s[2]-s[3]|+...+|s[m-1]-s[m]|
構想
各ページ番号がシーケンスの前後に現れるページ番号(例えば1 2 3 2 4では2前後に1 3 3 4が現れたことがある)を記録し(隣接するページ番号が同じであれば構わないことに注意)、それらの中位数を取ると、必ずこのページ番号を移動する最適解がある.すべてのページ番号を一度遍歴して、全体の最適解を取ればいいです.
コード#コード#
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
const int maxn = 100010;
const ll INF = 1e10L;
int s[maxn];
vector<int> ss[maxn];
ll close[maxn];
ll closee[maxn];
ll sum;
ll ans;
int ma;
int n,m;
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1 ; i <= m ; i ++) {
scanf("%d",&s[i]);
ma = max(ma,s[i]);
if(i != 1) {
sum += abs(s[i]-s[i-1]);
if(s[i] == s[i-1]) continue;
ss[s[i]].push_back(s[i-1]);
ss[s[i-1]].push_back(s[i]);
close[s[i]] += abs(s[i]-s[i-1]);
close[s[i-1]] += abs(s[i]-s[i-1]);
}
}
ans = sum;
for(int i = 1 ; i <= ma ; i ++) {
if(!ss[i].size()) continue;
sort(ss[i].begin(),ss[i].end());
int mid = ss[i].size()/2;
for(int j = 0 ; j < ss[i].size() ; j ++) {
closee[i] += abs(ss[i][j]-ss[i][mid]);
}
ans = min(ans,sum-close[i]+closee[i]);
}
cout << ans << endl;
return 0;
}