Codeforces Round #285 (Div.1 B & Div.2 D) Misha and Permutations Summation --二分+树状数组
题意:给出两个排列,求出每个排列在全排列的排行,相加,模上n!(全排列个数)得出一个数k,求出排行为k的排列。
解法:首先要得出定位方法,即知道某个排列是第几个排列。比如 (0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0).
拿排列(1,2,0)来说,首位是1,前面有cnt=1个小于1的没被用过的数(0),所以它的排行要加上(cnt=1)*2!,第二位为2,因为1已经放了,所以小于2的只有0了,即cnt=1个,所以,排行又要加上(cnt=1)*1!,所以排行为3.
推出一般性结论:

pre[i]表示小于 i 且没被占据的数的个数。我们可以用树状数组一边更新一边查询求得给出的两个排列的所有pre[]值,存到p数组:p1[i] = pre1[b1[i]],p2[i] = pre2[b2[i]]
然后Rank和为(p1[i]+p2[i])*(n-1)! + ... + (p1[n]+p2[n])*0! = p3[1]*(n-1)! + ... + p3[n]*0! ,但是得出的表达式可能不是规整的形式,这是我们需要检测一边,从后往前扫,如果p3[i] >= (n-i+1), 说明第 i 项已经超过 (n-i+1)*(n-i), 那么就应进位到(n-i+1)!, 即p3[i-1]+=1,依此类推,第1位的进位不再考虑。
最后得出规整的正确的p3[]序列,然后通过树状数组+二分在nlognlogn的复杂度将p3每位对应到结果排列的每位数上,即为上面求Rank(p)的反操作,不细讲了,想一想就知道了。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
using namespace std;
#define N 200107 int p1[N],p2[N],p3[N],c[N];
int n; int lowbit(int x) { return x&-x; }
void modify(int x,int val)
{
while(x <= n+)
{
c[x] += val;
x += lowbit(x);
}
}
int getsum(int x)
{
int res = ;
while(x > )
{
res += c[x];
x -= lowbit(x);
}
return res;
} int main()
{
int i,j,x;
while(scanf("%d",&n)!=EOF)
{
memset(c,,sizeof(c));
for(i=;i<=n;i++) modify(i,);
for(i=;i<=n;i++)
{
scanf("%d",&x);
x++;
p1[i] = getsum(x-);
modify(x,-);
}
memset(c,,sizeof(c));
for(i=;i<=n;i++) modify(i,);
for(i=;i<=n;i++)
{
scanf("%d",&x);
x++;
p2[i] = getsum(x-);
modify(x,-);
}
memset(p3,,sizeof(p3));
for(i=n;i>=;i--)
{
p3[i] += p1[i]+p2[i];
if(p3[i] >= (n-i+))
{
p3[i] = p3[i]-(n-i+);
if(i != ) p3[i-]++;
}
}
memset(c,,sizeof(c));
for(i=;i<=n;i++) modify(i,);
// for(i=1;i<=n;i++)
// cout<<p3[i]<<" ";
// cout<<endl;
for(i=;i<=n;i++)
{
int low = , high = n;
while(low <= high)
{
int mid = (low+high)/;
if(getsum(mid-) > p3[i])
high = mid-;
else if(getsum(mid-) == p3[i] && getsum(mid)-getsum(mid-) == )
high = mid-;
else if(getsum(mid-) == p3[i] && getsum(mid)-getsum(mid-) < )
low = mid+;
else if(getsum(mid-) < p3[i])
low = mid+;
}
modify(low,-);
printf("%d ",low-);
}
puts("");
}
return ;
}
比赛中写的代码,没有最简化,有很多冗余和多此一举的地方。
Codeforces Round #285 (Div.1 B & Div.2 D) Misha and Permutations Summation --二分+树状数组的更多相关文章
- Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) E. DNA Evolution 树状数组
E. DNA Evolution 题目连接: http://codeforces.com/contest/828/problem/E Description Everyone knows that D ...
- codeforces 1269E K Integers (二分+树状数组)
链接:https://codeforces.com/contest/1269/problem/E 题意:给一个序列P1,P2,P3,P4....Pi,每次可以交换两个相邻的元素,执行最小次数的交换移动 ...
- Codeforces Round #227 (Div. 2) E. George and Cards set内二分+树状数组
E. George and Cards George is a cat, so he loves playing very much. Vitaly put n cards in a row in ...
- Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) E. Cards Sorting 树状数组
E. Cards Sorting time limit per test 1 second memory limit per test 256 megabytes input standard inp ...
- Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Cards Sorting(树状数组)
Cards Sorting time limit per test 1 second memory limit per test 256 megabytes input standard input ...
- BestCoder Round #90 //div all 大混战 一题滚粗 阶梯博弈,树状数组,高斯消元
BestCoder Round #90 本次至少暴露出三个知识点爆炸.... A. zz题 按题意copy Init函数 然后统计就ok B. 博弈 题 不懂 推了半天的SG..... 结果这 ...
- Codeforces 1093E Intersection of Permutations (CDQ分治+树状数组)
题意:给你两个数组a和b,a,b都是一个n的全排列:有两种操作:一种是询问区间在数组a的区间[l1,r1]和数组b的区间[l2,r2]出现了多少相同的数字,另一种是交换数组b中x位置和y位置的数字. ...
- 图论/位运算 Codeforces Round #285 (Div. 2) C. Misha and Forest
题目传送门 /* 题意:给出无向无环图,每一个点的度数和相邻点的异或和(a^b^c^....) 图论/位运算:其实这题很简单.类似拓扑排序,先把度数为1的先入对,每一次少一个度数 关键在于更新异或和, ...
- 字符串处理 Codeforces Round #285 (Div. 2) B. Misha and Changing Handles
题目传送门 /* 题意:给出一系列名字变化,问最后初始的名字变成了什么 字符串处理:每一次输入到之前的找相印的名字,若没有,则是初始的,pos[m] 数组记录初始位置 在每一次更新时都把初始pos加上 ...
随机推荐
- Subway Icon Set – 306个像素完美的特制图标
这个图标集是306个优化的像素完美,精雕细琢的图标.为这些设备进行了优化:iOS.Windows Phone.Windows 8 and BlackBerry 10,提供 PNG, SVG, XALM ...
- css通用小笔记01——导航背景
很多刚接触前端的可能遇到一些css能解决的小问题,我现在总结了一些,将会逐渐和大家分享,先是导航的背景问题,在网页中常常看到,当鼠标放到一个导航按钮上面是,就会出现一些特效,比如背景,这是最常用的,我 ...
- Icon Font浅谈
这周继续在弄hybird app 的 UI框架的重构,进行到了编写换肤功能的阶段,而在做换肤之前,我想应该先弄一套框架内置的图标. 而图标无非就是两种做法: 1.图片 使用图片很正常,但是有缺陷的. ...
- SAP中日期时间函数总结
1.获得最后一天CALL FUNCTION 'FIMA_DATE_CREATE' EXPORTING I_DATE = I_DATE "输入 ...
- react native与现有的应用程序集成
(1)通过cocopods 集成 ,以下内容 参考 http://wiki.jikexueyuan.com/project/react-native/integration-existing.html ...
- phonegap创建的ios项目推送消息出现闪退现象
使用phonegap创建的ios项目,推送消息时,当程序在前台运行或者在后台运行状态下,推送消息过来,可以解析并且跳转: 但是在程序从后台退出的状态下,当消息推送过来的时候,点击通知栏,打开程序,程序 ...
- js window对象
BOM的核心对象是window,它表示浏览器的一个实例. 在浏览器中,window对象是(1)通过JavaScript访问浏览器窗口的一个接口 (2)ECMAScript规定的Global对象 1.全 ...
- [转]android笔记--Intent和IntentFilter详解
Intent用于启动Activity, Service, 以及BroadcastReceiver三种组件, 同时还是组件之间通信的重要媒介. 使用Intent启动组件的优势1, Intent为组件的启 ...
- js技术发展
将.NET代码编译为JavaScript 你可以使用如下工具将C#.F#以及其他.NET代码编译为JavaScript代码. Apps in Motion:允许使用C#来构建可以运行在任何设备上的We ...
- luemn PHP_CodeSniffer的安装
1.PHP_CodeSniffer是PEAR中的一个用PHP5写的用来检查嗅探PHP代码是否有违反一组预先设置好的编码标准的一个包,它是确保你的代码简洁一致的必不可少的开发工具,甚至还可以帮助程序员减 ...