UVA - 11525

题意:输出1~n的所有排列,字典序大小第∑k1Si∗(Ki)!个


学了好多知识

1.康托展开

X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!

其中a[i]为第i位是i往右中的数里 第几大的-1(比他小的有几个)。

其实直接想也可以,有点类似数位DP的思想,a[n]*(n-1)!也就是a[n]个n-1的全排列,都比他小

一些例子 http://www.cnblogs.com/hxsyl/archive/2012/04/11/2443009.html

如我想知道321是{1,2,3}中第几个大的数可以这样考虑 :

  第一位是3,当第一位的数小于3时,那排列数小于321 如 123、 213 ,小于3的数有1、2 。所以有2*2!个。再看小于第二位2的:小于2的数只有一个就是1 ,所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个 
。所以321是第6个大的数。 2*2!+1*1!是康托展开。

  再举个例子:1324是{1,2,3,4}排列数中第几个大的数:第一位是1小于1的数没有,是0个 0*3! 第二位是3小于3的数有1和2,但1已经在第一位了,所以只有一个数2 1*2! 。第三位是2小于2的数是1,但1在第一位,所以 
有0个数 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2个,1324是第三个大数。


2.树状数组求区间第k小

查了一堆资料,稍微有点明白了

用a[i]表示i出现次数,用一个树状数组c[]维护a[]

设第k小为x,那么sum(x)=k

我们的做法是用二进制反向构造x

cnt是当前x的排名(<=x的个数)

把x打成二进制,从高到低枚举(1<<i),可以发现x加上(1<<i)后lowbit值是不断减小的(lowbit的定义是最右面1对应的值)

cnt加上新x的c值(这一块二进制加上的效果相当于让x在树状数组上跳了一下,结果也就是当前sum(x)的结果)

if(x>=n||cnt+c[x]>=k) 就不加了

这样就找到了最大的比x小的元素,++就行了

其实就记住,用二进制构造x-1,c数组类比着加就行了

二进制逼近,反向求和的过程

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
const int N=5e5+,INF=1e6+;
inline int read(){
char c=getchar();int x=,f=;
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
}
int n,x,k;
int c[N];
inline int lowbit(int x){return x&-x;}
inline void add(int p,int v){
for(;p<=n;p+=lowbit(p)) c[p]+=v;
}
inline int sum(int p){
int res=;
for(;p>;p-=lowbit(p)) res+=c[p];
return res;
}
inline int kth(int k){
int x=,cnt=;
for(int i=;i>=;i--){
x+=(<<i);
if(x>=n||cnt+c[x]>=k) x-=(<<i);
else cnt+=c[x];
}
return x+;
}
int main(){
int T=read();
while(T--){
n=read();
memset(c,,sizeof(c));
for(int i=;i<=n;i++) add(i,);
for(int i=;i<=n;i++){
k=read()+;
x=kth(k);
printf("%d%c",x,i==n?'\n':' ');
add(x,-);
}
}
}

UVA11525 Permutation[康托展开 树状数组求第k小值]的更多相关文章

  1. 树状数组求第K小值 (spoj227 Ordering the Soldiers &amp;&amp; hdu2852 KiKi&#39;s K-Number)

    题目:http://www.spoj.com/problems/ORDERS/ and pid=2852">http://acm.hdu.edu.cn/showproblem.php? ...

  2. 树状数组求第k小的元素

    int find_kth(int k) { int ans = 0,cnt = 0; for (int i = 20;i >= 0;i--) //这里的20适当的取值,与MAX_VAL有关,一般 ...

  3. hdu 4217 Data Structure? 树状数组求第K小

    Data Structure? Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...

  4. POJ2985 The k-th Largest Group[树状数组求第k大值+并查集||treap+并查集]

    The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8807   Accepted ...

  5. *HDU2852 树状数组(求第K小的数)

    KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  6. poj 2985 The k-th Largest Group 树状数组求第K大

    The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8353   Accepted ...

  7. HDU 5249 离线树状数组求第k大+离散化

    KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...

  8. HDU 2852 (树状数组+无序第K小)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2852 题目大意:操作①:往盒子里放一个数.操作②:从盒子里扔掉一个数.操作③:查询盒子里大于a的第K小 ...

  9. 树状数组求第K大(From CLJ)

    ; <<log2[n];p;p>>=) if(a[ret+p]<=kth) kth-=a[ret+=p]; return ret;

随机推荐

  1. 简单回顾NPOI导入导出excel文件

    当前环境.net4.0 去官方下下载:  NOPI官网 关于NOPI的详细,这里就不再介绍. 在项目中,我们只需引入  NPOI.dll  就可以了. 接下来..................... ...

  2. 零基础如何学习java更有效呢?

    零基础学java,不知道该如何入手?也不知道学习的方向,很多人会问零基础怎么样学习,有没有什么入门的书籍推荐:只要方法正确,零基础学好java也是有机会的哦. 一.理解Java思想 Java是一门面向 ...

  3. PHP学习资料下载

    yii2教程以及手册 https://yunpan.cn/ckkhbccyqGVYg (提取码:09b8) mysql学习 链接: http://pan.baidu.com/s/1kUTC8tT 密码 ...

  4. Professional JavaScript for Web Developers 3rd Edition ---读书笔记

    1. DOMContentLoaded DOM树构建完成时触发该事件 load 页面加载完毕触发 原生js document.addEventListener('DOMContentLoaded', ...

  5. 学习笔记:Asp.Net MVC更新部分页面

    Asp.Net MVC 更新部分页面 设想我们有一篇文章下面的提交评论时如何只刷新评论内容部分, 方法一,利用ajax通过js代码实现. 方法二,利用Ajax.BeginForm()+部分视图实现. ...

  6. js鼠标滚轮滚动图片切换效果

    效果体验网址:http://keleyi.com/keleyi/phtml/image/12.htm HTML文件代码: <!DOCTYPE html PUBLIC "-//W3C// ...

  7. HTML5漂亮实用的电子书

    效果体验:http://hovertree.com/texiao/html5/2.htm 点击这里下载 支持多种系统Mac,PC,Android,iPhone,iPad和Windows Phone 支 ...

  8. 走进 .Net 单元测试

    走进 .Net 单元测试 Intro "不会写单元测试的程序员不是合格的程序员,不写单元测试的程序员不是优秀程序员." -- 一只想要成为一个优秀程序员的渣逼程序猿. 那么问题来了 ...

  9. iOS UITabBarController的使用

    UITabBarController 和 UINavigationController 几乎是iOS APP的标配. UITabBarController分栏(标签栏)控制器, 和UINavigati ...

  10. K近邻模型(k-NN)

    原理 K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一.该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻 ...