long long merge_and_count(int l, int r) { // range [l,r)
	if (l+1 >= r) return 0; // empty
	if (l+2 == r) { // [l,r) == [l,l+1] 要素2つだけ
		if (A[l] <= A[l+1]) return 0; // 逆転はなし
		std::swap(A[l], A[l+1]);
		return 1; // 逆転一つ
	}
	int m = (l+r)/2; // [l,r) == [l,m) + [m,r)
	long long cl = merge_and_count(l, m); // 左半分を再帰的に数える
	long long cr = merge_and_count(m, r); // 右半分を再帰的に数える
	long long c = 0; // 左と右を混ぜるときの逆転数
	int i=l, j=m; // iは[l,m)を動き, jは[m,r)を動いて、
	int k=l; // 小さいものから W[k] に書き込む
	while (i<m && j<r) { // A[i]とA[j]を比べながら進む
		if (A[i] <= A[j]) W[k++] = A[i++]; // 左半分の方が小さく逆転なし
		else {
			W[k++] = A[j++];
			c += m-i; // 左半分の方が大きい、左半分で未処理の要素だけ飛び越える
		}
	}
	while (i<m) W[k++] = A[i++]; // 左半分が余った場合
	while (j<r) W[k++] = A[j++]; // 右半分が余った場合
	//assert(k == r);
	std::copy(W+l, W+r, A+l);
	return cl + cr + c;
}
Ejemplo n.º 2
0
static void *sort_threaded (void *arg)
{
    NOTNULL(arg);
    
    Thread_context *context = (Thread_context *) arg;
    
    if ((context->depth >= THREAD_DEPTH) || (context->length < 1000))
    {
        context->merged = sort_recursive (context->length, context->numbers);
    }
    else
    {
        pthread_t thread_left = 0;
        pthread_t thread_right = 0;
        Thread_context context_left = {0};
        Thread_context context_right = {0};
        size_t length_left = 0;
        pthread_attr_t thread_attributes = {0};
        
        context_left.depth = context->depth + 1;
        context_right.depth = context->depth + 1;
        
        length_left = context->length / 2;
        
        context_left.length = length_left;
        context_left.numbers = context->numbers;
        
        context_right.length = context->length - length_left;
        context_right.numbers = context->numbers + length_left;
        
        pthread_attr_init (&thread_attributes);
        pthread_attr_setdetachstate (&thread_attributes, PTHREAD_CREATE_JOINABLE);
        
        pthread_create (&thread_left, &thread_attributes, sort_threaded, &context_left);
        pthread_create (&thread_right, &thread_attributes, sort_threaded, &context_right);
        
        pthread_attr_destroy (&thread_attributes);
        
        pthread_join (thread_left, NULL);
        pthread_join (thread_right, NULL);
        
        context->merged = merge_and_count (context_left.merged, context_right.merged);
    }
    
    if (context->depth)
    {
        pthread_exit (NULL);
    }
    
    return NULL;
}
long long int sort_and_count(std::vector<int> &v, int s, int e, std::vector<int> &c)
{
    if (s >= e - 1) { //if only one element
        return 0;
    }
    int  mid = (s + e) / 2;
    long long int x = sort_and_count(v, s, mid, c);

    long long int y = sort_and_count(v, mid, e, c);

    long long int z = merge_and_count(v, s, mid, e, c);

    return x + y + z;
}
Ejemplo n.º 4
0
void sort_and_count(SortedList *sl, int_l from_idx, int_l to_idx) {

    int_l length = to_idx - from_idx;

    // end case
    if (length == 1) { return; }

    int_l left_size = length / 2;
    int_l right_size = length - left_size;
    int_l med = from_idx + left_size;

    sort_and_count(sl, from_idx, med);
    sort_and_count(sl, med, to_idx);

    merge_and_count(sl, from_idx, med, to_idx);
}
int main(){
	int T,i,N;
	//PKU2299,aizu0167: バブルソートの交換回数
	//for(;scanf("%d",&N),N;printf("%lld\n",merge_and_count(0,N)))for(i=0;i<N;i++)scanf("%d",A+i);
	//hackerrank~runningtime,aizuALDS1~5D
	//scanf("%d",&N);for(i=0;i<N;i++)scanf("%d",A+i);printf("%lld\n",merge_and_count(0,N));
	//spojINVCNT,hackerrank~insertionsort
	//for(scanf("%d",&T);T--;printf("%lld\n",merge_and_count(0,N)))for(scanf("%d",&N),i=0;i<N;++i)scanf("%d",A+i);
	//codeiq432: 光線の交差数
	//for(N=0;~scanf("%d",A+N);N++);printf("%lld\n",merge_and_count(0,N));
	//codeiq838: あみだくじの最小本数
	//T=0,N=7;
	//std::vector<int>v(N);
	//std::iota(v.begin(),v.end(),1);
	//do{std::copy(v.begin(),v.end(),A);if(merge_and_count(0,N)==10)T++;}while(std::next_permutation(v.begin(),v.end()));
	//printf("%d\n",T); //573
	//kcs1009K: Nパズルの可解性
	//for(i=0;~(N=getchar());)if('0'<N&&N<'9')A[i++]=N-'0';
	//puts(merge_and_count(0,i)%2?"lmpossible":"Possible"); //"l"? lol!
	//atcoderutpc2014F: パリティ
	//for(scanf("%d",&T),getchar();T--;printf("%lld\n",merge_and_count(0,N)%2))for(N=0;~(A[N]=getchar())&&A[N]!='\n';N++);
	//kcs1031A
	//scanf("%d%d",&N,&T);for(i=0;i<N;i++)scanf("%d",A+i);printf("%lld\n",std::max(merge_and_count(0,N)-T,0LL));
	//masuipeobook25: オシャレな靴ひもの結び方
	//{0,5,4,5,3,4,2,3,1,2,0,1}のinversion countを取れば良い
	T=0,N=12;
	std::vector<int>v(N);
	for(i=0;i<N/2;i++)v[2*i]=v[2*i+1]=i;
	rotate(v.begin(),v.begin()+1,v.end());
	do{
		std::swap(v[N-2],v[N-1]);
		for(i=0;i<N/2;i++){
			if(v[2*i]>=v[2*i+1])break;//同じ穴に結線しているか、inversion countを行える条件を満たさない
		}
		if(i==N/2){
			std::copy(v.begin(),v.end(),A),T=std::max((long long)T,merge_and_count(0,N));
			if(T==45)std::cout<<v<<std::endl;
		}
		std::swap(v[N-2],v[N-1]);
	}while(std::next_permutation(v.begin()+1,v.end()-1));
	printf("%d\n",T);
}
Ejemplo n.º 6
0
static Array *sort_recursive (size_t length, uint32_t *numbers)
{
    NOTNULL(numbers);
    
    Array *sorted = NULL;
    
    if (length > 2)
    {
        size_t length_left = length / 2;
        
        sorted = merge_and_count (sort_recursive (length_left, numbers),
                                  sort_recursive (length - length_left, numbers + length_left));
    }
    else if (length == 2)
    {
        sorted = array_new (2);
        
        if (numbers [0] < numbers [1])
        {
            sorted->data [0] = numbers [0];
            sorted->data [1] = numbers [1];
        }
        else
        {
            sorted->data [0] = numbers [1];
            sorted->data [1] = numbers [0];
            
            sorted->h.inversions = 1;
        }
    }
    else if (length == 1)
    {
        sorted = array_new (1);
        
        sorted->data [0] = numbers [0];
    }
        
    return sorted;
}