【题目链接】:http://codeforces.com/problemset/problem/501/D

【题意】



给你两个排列;

求出它们的字典序num1和num2;

然后让你求出第(num1+num2)%n!个排列是什么;

(字典序);

【题解】



首先。

求出两个排列的字典序;

->康拓展开搞出来;

然后得到

v1[1]∗(n−1)!+..+v1[i]∗(n−i)!+...+v1[n]∗(0)!

的形式

这里v1[i]是i+1..n中比a[i]小的数的个数;

同样的能够得到

v2[1]∗(n−1)!+..+v2[i]∗(n−i)!+...+v2[n]∗(0)!

这里v2[i]是i+1..n中比b[i]小的数的个数;

然后考虑把两个数加起来;

即合并成

(v1[1]+v2[1])∗(n−1)!+..+(v1[i]+v2[i])∗(n−i)!+...+(v1[n]+v2[n])∗(0)!

这里合并之后(v1[i]+v2[i])的值不一定会比(n-i)小;

这就可能让某一个v1[i]+v2[i]进到前一位去;

比如(3+3)4!进到x*5!去;

就会让x加1

因为(3+3)*4!可以写成(5+1)*4!的形式;

即5!+1*4!

也即让5!的系数+1了;

然后4!的系数会减去5

一直往前进位就好;

别忘了要%n!

所以n!的系数可以不用管它了;

然后就能得到(num1+num2)%n!

这个排列的康拓展开的各个

v值了;

从第1位开始;

根据v[1],可以得到比a[1]小的数有多少个;

然后直接让他等于那个v[1]+1;

然后考虑v[2];

这个时候仍旧能够直接得到比a[2]小的数有多少个;

但是不能再包括a[1]了,因为是从2+1..n这个范围里面找比a[2]小的数的个数;

根据找到的合适的位置,确定a[2]即可

以此类推获得a[n]

(可以用树状数组+二分搞出来)

掌握了康拓展开、逆康拓展开吧..

还是很优秀的。



【Number Of WA】



0



【完整代码】

#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define ms(x,y) memset(x,y,sizeof x)
#define Open() freopen("F:\\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0),cin.tie(0) typedef pair<int,int> pii;
typedef pair<LL,LL> pll; const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 2e5+100; int n; struct BIT
{
int data[N];
int lowbit(int x){
return (-x)&x;
}
int get_sum(int x){
int sum = 0;
while (x > 0){
sum+=data[x];
x-=lowbit(x);
}
return sum;
}
void add(int x,int y)
{
while (x<=n){
data[x]+=y;
x+=lowbit(x);
}
}
void init()
{
ms(data,0);
}
}; BIT c;
int a[N],b[N],v[N],ans[N]; void kangtuo(int *a,BIT &bit){
bit.init();
rep1(i,1,n){
int s = a[i]-1-bit.get_sum(a[i]-1);
bit.add(a[i],1);
v[i]+=s;
}
} int Bsearch(int l,int r,int k)
{
int ans = 0;
while (l <= r)
{
int mid = (l+r)>>1;
int temp = c.get_sum(mid);
if (mid-temp>=k){
ans = mid;
r = mid-1;
}
else
l = mid+1;
}
return ans;
} void nikangtuo(BIT &bit){
bit.init();
rep1(i,1,n){
int s = Bsearch(1,n,v[i]+1);
ans[i] = s;
c.add(s,1);
}
} int main(){
//Open();
Close();//scanf,puts,printf not use
//init??????
cin >> n;
rep1(i,1,n)
cin>>a[i],a[i]++;
rep1(i,1,n)
cin>>b[i],b[i]++;
kangtuo(a,c);
kangtuo(b,c);
rep2(i,n,1){
int you = n-i+1;
v[i-1]+=v[i]/you;
v[i]%=you;
}
nikangtuo(c);
rep1(i,1,n)
{
cout<<ans[i]-1<<(i==n?'\n':' ');
}
return 0;
}

最新文章

  1. MTK MT33xx型GPS的NMEA协议解析实例
  2. Windows和Linux都有的Copy-on-write技术
  3. keepalived高可用
  4. C 语言学习的第 03 课:你的 idea 是怎么变成能够执行的程序的
  5. SVN命令使用详解
  6. C# 域用户操作(转)
  7. 记录一次MVC 3.0错误 HTTP 404您正在查找的资源(或者它的一个依赖项)可能已被移除,或其名称已更改,或暂时不可用。请检查以下 URL 并确保其拼写正确。
  8. 常用sql命令
  9. javascript文件加载模式与加载方法
  10. 小甲鱼Python第十讲课后题---
  11. xmanagr 注册机执行ubuntu 桌面程序,ubuntu无需安装 桌面环境
  12. bash编程-Shell变量
  13. vCenter机器查找功能不可用的解决
  14. AngularJS中转换响应内容
  15. 解决rpm conflicts with file from package的两个方法
  16. Beta阶段冲刺三
  17. How to become a successful bug bounty hunter
  18. HDU 3746 Cyclic Nacklace(KMP+最小循环节)题解
  19. angluarjs ng-repeat 行号
  20. 20155303 2016-2017-2 《Java程序设计》第九周学习总结

热门文章

  1. Android ViewGroup拦截触摸事件具体解释
  2. chmod和chown命令具体使用方法
  3. MFC exe使用C++ dll中的std::string 崩溃
  4. bzj1106: [POI2007]立方体大作战tet
  5. Swift - 制作一个在线流媒体音乐播放器(使用StreamingKit库)
  6. python fuzzy c-means demo
  7. 谷歌浏览器 —— 快捷键(vimium:像使用 vim 一样操作当前页面)
  8. 杂项-Java:Shiro(Java安全架构)
  9. 40.DOM读取XML
  10. maven 项目加载本地JAR