康拓展开+树状数组+二分: 详解
/* ***********************************************
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;
}