SPOJ:GENERAL(超出时间限制)

时间:2016-06-27 16:44:10

标签: c++ arrays algorithm sorting

我一直试图在spoj上解决这个简单的问题(http://br.spoj.com/problems/GENERAL/)已经有一段时间了,但由于某些原因我一直在获得TLE(超出时间限制)。

由于问题是葡萄牙语,因此问题的简要说明就是这样(没有故事):

  

您将获得一个大小 N 的数组,您必须安排数组   升序,这样元素只能与之交换   距离它 k 的元素。如果阵列可以   排序然后打印排列它们所需的互换数量   升序,如果无法排序打印 impossivel

这是我的代码::

#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 。在每次迭代中,我检查 ik 元素与距离 k 的元素,如果它们要交换,那么我交换它们并增加所需的交换数量,否则我什么都不做。然后我检查从 ik i 的元素,如果它们按升序排列,如果不是我打破循环并打印&#34; impossivel&#34;,否则我将 i 更改为 ik 并再次执行循环。根据我的逻辑,在每次迭代后,最后的 k 元素将按升序排列,如果可以对它们进行排序,因为在每一步我都会移动更大的元素。

这对你来说是否正确?如何进一步优化?在此先感谢您的帮助。 :)

1 个答案:

答案 0 :(得分:3)

分别分为k个n / k个元素的子列表。

检查不可能状况。

不可能条件

设k = 2,

3 4 1 2是阵列

对于n / k列表,维护数组以查看O(1)中是否存在数字。

例如。间隔为2

我们可以分为两个子列表,3 1和4 2 现在我们知道sort is

1 2 3 4(使用计数排序作为1和n O(n)之间的高度)

所以,我们预计第一名是1。现在问,可以1来这里吗?如果它只在子列表中。[Y]

如果[N]说&#34;不可能&#34;

如果不可能我们就完成了其他事情。

k次合并排序,k * n / k(log(n / k))

(反转次数等于对数组进行排序的相邻互换的最小数量[已知属性] 参考: Sorting a sequence by swapping adjacent elements using minimum swaps

方法的复杂性是n log n,很容易通过:)