LGOJ AFOI-19 T1 【数码排序】

戳这里看原题

原题:

题目背景

小L从虚拟世界里出来啦!

题目描述

逃出来的同时,也有一部分数码逃了出来,吵着闹着让小L帮他们排序

虚拟世界的数码都是不可见的

小L目前只会选择排序,插入排序,冒泡排序,归并排序

所以小L想问他在最坏情况下最少需要几次比较,才能使序列有序

排序的模板代码:

//归并
void msort(int l, int r) {
	if(l == r) return;
	int mid = (l + r) >> 1;
	msort(l, mid);
	msort(mid + 1, r);
	int i = l, j = mid + 1, k = l;
	while(i <= mid && j <= r)
		if(a[i] <= a[j]) ls[k++] = a[i++];
		else ls[k++] = a[j++];
	while(i <= mid) ls[k] = a[i], k++, i++;
	while(j <= r) ls[k] = a[j], k++, j++;
	for(int i = l;i <= r;i++) a[i] = ls[i];
}
//冒泡
for(int j = 1;j < n; j++)
	for(int i = 1;i <= n - j; i++)
		if(a[i] > a[i + 1])
			swap(a[i], a[i + 1]);
//插排
for(int i = 2;i <= n;i++) {
	int p = i;
	while(p > 1 && a[p] > a[p - 1]) {
		swap(a[p], a[p - 1]);
		p--;
	}
}
//选择
for(int i = 1;i < n;i++) {
	int maxx = a[i], p = i;
	for(int j = i + 1;j <= n;j++)
		if(a[j] > maxx) maxx = a[p = j];
	swap(a[i], a[p]);
}

输入格式

输入仅有一行,给定一个正整数\(n\),表示序列的长度

输出格式

输出最小的比较次数







問題の解

容易得到递推式:

\[ f(i)=\left\{ \begin{aligned} & f(\lfloor \frac{i}{2} \rfloor)+f(\lfloor \frac{i}{2} \rfloor+1) +i-1 ,(i\ is\ odd)\\ & 2f(\lfloor \frac{i}{2}\rfloor) +i-1,(i\ is\ even)\\ \end{aligned} \right. \qquad , i \geq 2 \]

初始值\(f(1)=0\)过于显然。

コード:

#include<bits/stdc++.h>
using namespace std;
#define ll unsigned long long 
ll n;
const int N=1e7+10;
//ll f[N];
map<ll,ll> r;
ll find(ll i)
{
    if(i==1)return 0;
    if(i==2)return 1;
    if(i==3)return 3;
    if(r[i])return r[i];
    if(i&1)return r[i]=find((i>>1))+find((i>>1)+1)+i-1;
    else return r[i]=(find((i>>1))<<1)+i-1;
}
int main()
{
    cin>>n;
    cout<<find(n);
    
    return 0;
}
posted @ 2019-11-08 10:45  miyasaka  阅读(322)  评论(0)    收藏  举报