首页 > 其他 > 详细

CF501D Misha and Permutations Summation(康托展开)

时间:2015-01-12 20:49:12      阅读:353      评论:0      收藏:0      [点我收藏+]

以前写康托展开都是直接O(n^2),碰到了一定要nlogn的,存个代码。

#pragma warning(disable:4996)
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;

#define maxn 210000

int bit[maxn];
int n;

void upd(int i)
{
	while (i <= n){
		bit[i] += 1;
		i += i&(-i);
	}
}

void dec(int i)
{
	while (i <= n){
		bit[i] -= 1;
		i += i&(-i);
	}
}

int cal(int i)
{
	int ret = 0;
	while (i > 0){
		ret += bit[i];
		i -= i&(-i);
	}
	return ret;
}

int solve(int x)
{
	int l = 1, r = n+1;
	while (l < r)
	{
		int mid = (l + r) >> 1;
		int tx = cal(mid);
		if (tx < x) l = mid + 1;
		else r = mid;
	}
	return l;
}

int a[maxn];
int b[maxn];
int c[maxn];
int va[maxn];
int vb[maxn];
int vc[maxn];

int main()
{
	while (cin >> n)
	{
		for (int i = 0; i < n; ++i){
			scanf("%d", a + i); a[i]++;
		}
		for (int i = 0; i < n; ++i){
			scanf("%d", b + i); b[i]++;
		}
		memset(bit, 0, sizeof(bit));
		for (int i = n - 1; i >= 0; --i){
			va[i] = cal(a[i]);
			upd(a[i]);
		}
		memset(bit, 0, sizeof(bit));
		for (int i = n - 1; i >= 0; --i){
			vb[i] = cal(b[i]);
			upd(b[i]);
		}
		reverse(va, va + n);
		reverse(vb, vb + n);
		memset(vc, 0, sizeof(vc));
		int carry = 0;
		for (int i = 1; i < n; ++i){
			vc[i] = (carry + va[i] + vb[i]) % (i + 1);
			carry = (carry + va[i] + vb[i]) / (i + 1);
		}
		reverse(vc, vc + n);
		memset(bit, 0, sizeof(bit));
		for (int i = 1; i <= n; ++i){
			upd(i);
		}
		for (int i = 0; i < n; ++i){
			c[i] = solve(vc[i]+1);
			dec(c[i]);
		}
		for (int i = 0; i < n; ++i){
			if (i) printf(" ");
			printf("%d", c[i]-1);
		}
		puts("");
	}
	return 0;
}

 

CF501D Misha and Permutations Summation(康托展开)

原文:http://www.cnblogs.com/chanme/p/4219563.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!