CF——501D(变进制数康托展开)

D. Misha and Permutations Summation

time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard 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§ 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 = (a 0, a 1, …, a n - 1) is called to be lexicographically smaller than permutation b = (b 0, b 1, …, b n - 1), if for some k following conditions hold: a 0 = b 0, a 1 = b 1, …, a k - 1 = b k - 1, a k < b k.

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.

Examples
inputCopy
2
0 1
0 1
outputCopy
0 1
inputCopy
2
0 1
1 0
outputCopy
1 0
inputCopy
3
1 2 0
2 1 0
outputCopy
1 0 2
Note
Permutations of numbers from 0 to 1 in the lexicographical order: (0, 1), (1, 0).

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

In the second sample Ord§ = 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§ = 3 and Ord(q) = 5, so the answer is .

变进制数康托展开,大佬博客点这里

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+500;
int a[N],b[N],c[N],ans[N];
int bit[N];
int n;
struct tree {
	int data;
	int l,r;
} t[N*4];
void add(int x) {
	while(x<=n) {
		bit[x]++;
		x+=x&-x;
	}
	return;
}
int ask(int x) {
	int ans=0;
	while(x) {
		ans+=bit[x];
		x-=x&-x;
	}
	return ans;
}
void pushup(int p) {
	t[p].data=t[p*2].data+t[p*2+1].data;
	return;
}
void build(int p,int l,int r) {
	t[p].data=0;
	t[p].l=l;
	t[p].r=r;
	if(l==r)return;
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
}
void change(int p,int x) {
	if(t[p].l==t[p].r) {
		t[p].data=1;
		return;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(x<=mid)change(p*2,x);
	else change(p*2+1,x);
	pushup(p);
}
int Ask(int p,int x) {
	if(t[p].l==t[p].r) {
		return t[p].l;
	}
	int mid=(t[p].l+t[p].r)/2;
	if(mid-t[p].l+1-t[p*2].data>x)Ask(p*2,x);
	else Ask(p*2+1,x-(mid-t[p].l+1-t[p*2].data));
}
int main() {
	scanf("%d",&n);
	int x;
	for(int i=1; i<=n; ++i) {
		scanf("%d",&x);
		x++;
		a[i]=x-1-ask(x);
		add(x);
	}
	memset(bit,0,sizeof(bit));
	for(int i=1; i<=n; ++i) {
		scanf("%d",&x);
		x++;
		b[i]=x-1-ask(x);
		add(x);
	}
	int yu=0;
	for(int i=n; i>=1; --i) {
		c[i]=(a[i]+b[i]+yu)%(n+1-i);
		yu=(a[i]+b[i]+yu)/(n+1-i);
	}
	build(1,1,n);
	for(int i=1; i<=n; ++i) {
		ans[i]=Ask(1,c[i]);
		change(1,ans[i]);
	}
	for(int i=1; i<=n; ++i) {
		printf("%d ",ans[i]-1);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值