码迷,mamicode.com
首页 > 其他好文 > 详细

CF501D Misha and Permutations Summation(康托展开)

时间:2015-01-12 20:51:54      阅读:195      评论: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
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!