我尝试解决这个简单的问题(http://br.spoj.com/problems/GENERAL/)已经有相当一段时间了,但是由于某些原因,我一直在争取TLE (超过时间限制)。
由于问题是用葡萄牙文写的,对问题的简要描述如下(没有故事):
给你一个N大小的数组,你必须按升序排列数组,这样一个元素只能与离它很远的元素交换。如果可以对数组进行排序,则打印按升序排列所需的交换数量,如果不能排序,则打印不可能。
这是我的代码:
#include <iostream>
#include <cstdio>
using namespace std;
int a[100005];
int main() {
int t;
int n, k;
scanf("%d", &t); //number of test cases
while(t--) {
scanf("%d %d", &n, &k);
bool result = true;
int count = 0;
for(int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
for(int i = n; i > 0; i = i - k) {
int j = 0;
for( ; j < i - k; j++) {
if(a[j] > a[j + k]) {
int temp = a[j];
a[j] = a[j + k];
a[j + k] = temp;
count++;
}
}
for( ; j < i - 1; j++) {
if(a[j] > a[j + 1]) {
result = false;
break;
}
}
if(!result)
break;
}
if(result)
printf("%d\n", count);
else
printf("impossivel\n");
}
}
我的逻辑是:我对数组执行N/k迭代。我将循环变量i初始化为N。在每次迭代中,我检查i-k元素与元素之间的距离k,如果要交换它们,然后交换它们并增加所需的交换数量,否则我什么也不做。然后我检查从i-k到i的元素,如果它们按升序排列,如果不按升序排列,则断开循环并打印"impossivel",否则我会将i更改为i-k,然后再次执行循环。根据我的逻辑,每次迭代之后,最后一个k元素将按升序排列,如果可能的话,因为在每一步,我都会将更大的元素移向右边。
你觉得这样对吗?怎样才能进一步优化这一点?谢谢你提前提供帮助。:)
发布于 2016-06-27 10:44:46
分离为n/k元素的k个子列表。
检查不可能的情况。
不可能条件
设k=2,
3 4 1 2是数组
对于n/k列表,保持数组以查看O(1)中是否存在一个数字。
就像。间隔为2
我们可以分为两个子列表,3,1和4,2,现在我们知道排序是
1 2 3 4(使用计数排序作为介于1和n(N)之间的高度)
所以,我们期望第一名是1。现在问,我能来这里吗?如果它在sublist.Y中就好了。
如果N说“不可能”
如果不可能,我们就继续下去。
K次合并排序,k* n/k(log(n/k))
(倒置数等于排序数组已知属性的最小相邻掉期数,参见:Sorting a sequence by swapping adjacent elements using minimum swaps )
方法的复杂性是n log,它很容易通过:)
https://stackoverflow.com/questions/38059158
复制相似问题