Codeforces 501D. Misha and Permutations Summation 康拓展开+树状数组+二分


康拓展开+树状数组+二分:   详解

D. Misha and Permutations Summation
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Let's define the sum of two permutations p and q of numbers 0, 1, ..., (n - 1) as permutation , where Perm(x) is the x-th lexicographically permutation of numbers 0, 1, ..., (n - 1) (counting from zero), and Ord(p) is the number of permutation p in the lexicographical order.

For example, Perm(0) = (0, 1, ..., n - 2, n - 1)Perm(n! - 1) = (n - 1, n - 2, ..., 1, 0)

Misha has two permutations, p and q. Your task is to find their sum.

Permutation a = (a0, a1, ..., an - 1) is called to be lexicographically smaller than permutation b = (b0, b1, ..., bn - 1), if for some k following conditions hold: a0 = b0, a1 = b1, ..., ak - 1 = bk - 1, ak < bk.

Input

The first line contains an integer n (1 ≤ n ≤ 200 000).

The second line contains n distinct integers from 0 to n - 1, separated by a space, forming permutation p.

The third line contains n distinct integers from 0 to n - 1, separated by spaces, forming permutation q.

Output

Print n distinct integers from 0 to n - 1, forming the sum of the given permutations. Separate the numbers by spaces.

Sample test(s)
input
2
0 1
0 1
output
0 1
input
2
0 1
1 0
output
1 0
input
3
1 2 0
2 1 0
output
1 0 2
Note

Permutations of numbers from 0 to 1 in the lexicographical order: (0, 1), (1, 0).

In the first sample Ord(p) = 0 and Ord(q) = 0, so the answer is .

In the second sample Ord(p) = 0 and Ord(q) = 1, so the answer is .

Permutations of numbers from 0 to 2 in the lexicographical order: (0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0).

In the third sample Ord(p) = 3 and Ord(q) = 5, so the answer is .


/* ***********************************************
Author        :CKboss
Created Time  :2015年03月25日 星期三 18时57分39秒
File Name     :CF501D.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

const int maxn=200200;

int n;
int a[maxn],b[maxn],c[3][maxn];

/************************************/

int sum[maxn];

int lowbit(int x) { return x&(-x); }

void add(int p,int v=1)
{
	for(int i=p;i<=n;i+=lowbit(i)) sum[i]+=v;
}

int get(int p)
{
	int ret=0;
	for(int i=p;i;i-=lowbit(i)) ret+=sum[i];
	return ret;
}

/************************************/

bool on[maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	scanf("%d",&n);
	for(int i=0;i<n;i++) 
	{
		scanf("%d",a+i); a[i]++;
		int before=get(a[i]);
		c[0][i]=a[i]-1-before;
		add(a[i]);
	}

	memset(sum,0,sizeof(sum));
	for(int i=0;i<n;i++) 
	{
		scanf("%d",b+i); b[i]++;
		int before=get(b[i]);
		c[1][i]=b[i]-1-before;
		c[2][i]=c[0][i]+c[1][i];
		add(b[i]);
	}

	for(int i=n-1;i>0;i--)
	{
		int j=n-1-i;
		if(c[2][i]>j) 
		{
			c[2][i]-=j+1; c[2][i-1]++;
		}
	}
	c[2][0]%=n;


	memset(sum,0,sizeof(sum));
	memset(on,true,sizeof(on));

	for(int i=1;i<=n;i++) add(i);

	vector<int> vi;

	for(int i=0;i<n;i++)
	{
		int goal=c[2][i];
		int low=0,high=n,ans=-1;

		while(low<=high)
		{
			int mid=(low+high)/2;
			int s=get(mid);

			if(s==goal)
			{
				if(on[mid+1]==true)
				{
					ans=mid+1; break;
				}
				else low=mid+1;
			}
			else if(s<goal) low=mid+1;
			else if(s>goal) high=mid-1;
			
		}
		on[ans]=false; add(ans,-1);
		vi.push_back(ans-1);
	}

	for(int i=0;i<n;i++) printf("%d ",vi[i]);
	putchar(10);
    
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值