C++ 优化代码以在SPOJ上传递TLE的建议

C++ 优化代码以在SPOJ上传递TLE的建议,c++,algorithm,optimization,data-structures,C++,Algorithm,Optimization,Data Structures,我试图解决一个类似这样的问题: merge(left, middle, right, array) temp = new array k = 0, i = left, j = middle + 1 while i <= middle and j <= right if array[i] < array[j] temp[k++] = array[i] // array[i] is also smaller than all array

我试图解决一个类似这样的问题:

merge(left, middle, right, array)
  temp = new array
  k = 0, i = left, j = middle + 1

  while i <= middle and j <= right
    if array[i] < array[j]
      temp[k++] = array[i]
      // array[i] is also smaller than all array[j+1], ..., array[right]
      globalSum += array[i] * (right - j + 1)
    else
      // same as the classical function

给我n个数字(1这里有另一种方法:这个问题类似于计算反转,只是你必须对负责生成反转的元素求和。我们可以使用合并排序来解决这个问题。修改合并函数如下:

merge(left, middle, right, array)
  temp = new array
  k = 0, i = left, j = middle + 1

  while i <= middle and j <= right
    if array[i] < array[j]
      temp[k++] = array[i]
      // array[i] is also smaller than all array[j+1], ..., array[right]
      globalSum += array[i] * (right - j + 1)
    else
      // same as the classical function
合并(左、中、右、数组)
temp=新阵列
k=0,i=左,j=中+1

虽然我我认为你的方法是很好的。我在这方面做了一点尝试,没有找到比你的方法更好的方法

不过,您的代码中有几个错误。有几个地方存在整数溢出。您应该更改为:

long long a[max];

更明显的错误是,对小于或等于当前数字的数字求和。要解决此问题,可以添加第二个全局数组来跟踪每个值的计数:

int b[max];
...
...
    for(int i=0;i<max;i++)
        a[i]=b[i]=0;
    ...
    ...
        res += (sum(idx)-(++b[idx]*val));
intb[max];
...
...

对于(int i=0;我能提供一个例子吗?例如,
5 2 3 9 6 4
的预期输出是什么?还不清楚。你能给出一个分步的例子吗?我猜
0+0+2+9+10+6=27
。我在他现有的样本中逐步添加了一个。有多慢?你的代码似乎正确且快速。@IVlad:我正在使用printf()和scanf()为了这个目的,我认为最好是用C++代码而不是使用CIN和CUT。你确定它需要0.2秒,因为我在SPJ机器上运行它,它需要超过3秒。我有一个疑问。你真的认为只有慢IO是程序慢的原因吗?我这么说是因为我在SpJ上提交了其他问题。nd即使是面向IO的问题,使用我在上述代码中定义的函数read()应该足以给我一个可接受的答案。我已经开始怀疑我用BIT解决问题的方法。也许我应该从头开始,开始思考一种比这个算法快得多的新算法(我认为这是可能的。BIT通常非常快,所以我至少会在从头开始之前尝试一下。不过我不能肯定。采用arr[n]循环之外对我不起作用。我仍然得到TLE。顺便说一句,谢谢你为我的问题花费宝贵的时间。我认为你的怀疑是正确的:我无法用我的建议消除TLE错误。我想回到绘图板。如果我想到什么,我会编辑这个。谢谢IVlad的帮助。终于得到了我原创作品的AC按照弗雷泽的建议更正错误后进行编码。我在1.41秒内得到AC。我仍然想知道为什么它需要那么多时间。如果你的递归方法可以在0.5秒内得到AC,那么为什么我的位代码(通常认为是更快的位代码)需要太多时间?你能帮我弄清楚吗?谢谢“+1”为了找出我程序中的一个大错误,但解决方案并不令人印象深刻。一个更好的解决方案是让res+=sum(idx-1)因为我必须删除所有与当前值相等的相同值。我尝试过。效果很好。不需要额外的数组来跟踪每个术语的频率。但我的问题仍然是spoj上的TLE。如果有任何帮助,我们将不胜感激。谢谢。好的-我并不奇怪有更好的方法来处理错误:-)不错的一个。另外,如果您将0作为数字的有效值,您的解决方案将挂起在
add
函数中,因为
0+=(0&-0);==0
。我不清楚0是否为有效输入,但如果是,这可能是问题所在。
    #include<stdio.h>
#include <iostream>

using namespace std;

#define max 100001

int n;
long long res = 0;

int temp[max];
int arr[max];
void merge(int left, int m, int right)
{
    int k = 0;
    int i = left, j = m + 1;
    while (i <= m && j <= right)
        if (arr[i] < arr[j])
        {
            temp[k++] = arr[i];
            res += (long long)(right - j + 1) * arr[i++];
        }
        else
            temp[k++] = arr[j++];

    while (j <= right)
        temp[k++] = arr[j++];
    while (i <= m)
        temp[k++] = arr[i++];

    for (int i = 0; i < k; ++i)
        arr[left + i] = temp[i];
}

void sort(int left, int right)
{
    if (left < right)
    {
        int m = left + (right - left) / 2;
        sort(left, m);
        sort(m + 1, right);
        merge(left, m, right);
    }
}

int main()
{
    int t;
    scanf("%d", &t);
    for(int w=0;w<t;w++)
    {
        scanf("%d", &n);
        for(int i=0;i<n;i++)
            scanf("%d", &arr[i]);

        res=0;
        sort(0, n - 1);

        printf("%lld\n",res);
    }

    return 0;
}
long long a[max];
long long sum(int idx){
long long s=0;
int b[max];
...
...
    for(int i=0;i<max;i++)
        a[i]=b[i]=0;
    ...
    ...
        res += (sum(idx)-(++b[idx]*val));