分析

简述“康托展开”

康托展开是一个全排列到一个自然数的双射,常用于构建hash表时的空间压缩。设有\(n\)个数\((1,2,3,4,…,n)\),可以有组成不同(\(n!\)种)的排列组合,康托展开表示的就是是当前排列组合在\(n\)个不同元素的全排列中的名次。式子表示:

\[X=\sum_{i=1}^{n}a_i*(i-1)!
\]

\(\rightarrow\)

\[X=a_n*(n-1)!+a_{n-1}*(n-2)!+...+a_i*(i-1)!+...+a_1*0!
\]

其中, \(a_i\)为整数,并且\(0\leq a_i\leq i, 0 < i \leq n,\) 表示当前未出现的的元素中排第几个,这就是康托展开。

推论

根据康托展开,\(S_i\)就是第\(i\)位上可选的数中比第\(i\)位上应选的数小的数的个数。那么此题转化为求总区间第\(S_i+1\)大。一颗权值线段树解决问题,不用持久化。康托展开的排名也是基于0的,所以也不用调用STL的last_permutation().

算法流程

  1. 用权值线段树求出总区间第\(S_i+1\)大,记答案为\(ans\)并输出
  2. 将权值线段树的\([ans,ans]\)叶节点置0

就这么简单

时间复杂度

对于单组数据,执行一次上述算法流程需要\(O(\log k)\)时间,而要执行\(k\)次,所以单组数据的时间复杂度为\(O(k\log k)\)。有\(T\)组数据所以总时间复杂度为\(O(T\cdot k\log k)\)

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define rg register
template<typename T>T read(T&x)
{
T data=0;
int w=1;
char ch=getchar();
while(ch!='-'&&!isdigit(ch))
ch=getchar();
if(ch=='-')
w=-1,ch=getchar();
while(isdigit(ch))
data=data*10+ch-'0',ch=getchar();
return x=data*w;
}
using namespace std;
const int MAXK=5e4+7;
struct SegTree
{
int sum;
}ST[MAXK<<2];
#define root ST[o]
#define lson ST[o<<1]
#define rson ST[o<<1|1]
void pushup(int o)
{
root.sum=lson.sum+rson.sum;
} void build(int o,int l,int r)
{
if(l==r)
{
root.sum=1;
return;
}
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
pushup(o);
} int qkth(int o,int l,int r,int rnk)
{ // 边找边删,简化操作
if(l==r)
{
root.sum=0;
return l;
}
int mid=(l+r)>>1,ans;
if(rnk<=lson.sum)
ans=qkth(o<<1,l,mid,rnk);
else
ans=qkth(o<<1|1,mid+1,r,rnk-lson.sum);
pushup(o);
return ans;
} int main()
{
// freopen("UVa11525.in","r",stdin);
// freopen("UVa11525.out","w",stdout);
int T;
read(T);
while(T--)
{
memset(ST,0,sizeof(ST));
int k;
read(k);
build(1,1,k);
for(rg int i=1;i<=k;++i)
{
int s; // 不用开s数组,节省空间
read(s);
printf("%d%c",qkth(1,1,k,s+1),i==k?'\n':' ');
}
}
}

Hint

这题卡输出格式,必须按我那样写,不然会WA。(我就WA了好几次。)

UVA11525 【Permutation】的更多相关文章

  1. POJ 3187【permutation】

    POJ 3187 给定N值,从而确定了数据的范围及长度,暴力枚举数列,接下来类似杨辉三角的递推计算.注permutation从递增有序数列开始枚举,枚举到符合sum值时退出即可 #include &l ...

  2. POJ 2718【permutation】

    POJ 2718 问题描述: 给一串数,求划分后一个子集以某种排列构成一个数,余下数以某种排列构成另一个数,求这两个数最小的差,注意0开头的处理. 超时问题:一开始是得到一个数列的组合之后再从中间进行 ...

  3. 【agc030f】Permutation and Minimum(动态规划)

    [agc030f]Permutation and Minimum(动态规划) 题面 atcoder 给定一个长度为\(2n\)的残缺的排列\(A\),定义\(b_i=min\{A_{2i-1},A_{ ...

  4. 【题解】CF359B Permutation

    [题解]CF359B Permutation 求一个长度为\(2n\)的序列,满足\(\Sigma |a_{2i}-a_{2i-1}|-|\Sigma a_{2i}-a_{2i-1}|=2k\) 这种 ...

  5. 【线性代数】2-7:转置与变换(Transposes and Permutation)

    title: [线性代数]2-7:转置与变换(Transposes and Permutation) toc: true categories: Mathematic Linear Algebra d ...

  6. 【搜索】【并查集】Codeforces 691D Swaps in Permutation

    题目链接: http://codeforces.com/problemset/problem/691/D 题目大意: 给一个1到N的排列,M个操作(1<=N,M<=106),每个操作可以交 ...

  7. 【数学】HDU 5753 Permutation Bo

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5753 题目大意: 两个序列h和c,h为1~n的乱序.h[0]=h[n+1]=0,[A]表示A为真则为 ...

  8. 【原创】开源.NET排列组合组件KwCombinatorics使用(二)——排列生成

           本博客所有文章分类的总目录:本博客博文总目录-实时更新 本博客其他.NET开源项目文章目录:[目录]本博客其他.NET开源项目文章目录 KwCombinatorics组件文章目录: 1. ...

  9. 【原创】开源Math.NET基础数学类库使用(06)直接求解线性方程组

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

随机推荐

  1. LeetCode--067--二进制求和

    问题描述: 给定两个二进制字符串,返回他们的和(用二进制表示). 输入为非空字符串且只包含数字 1 和 0. 示例 1: 输入: a = "11", b = "1&quo ...

  2. PHP函数总结 (一)

    <?php /** * 原理: * 函数不调用不执行,定义函数时,会将 * 函数放到内存中代码段,当调用函数时去内存 * 中函数名称所在位置中执行函数体,执行完后 * 将控制权移交回给调用函数的 ...

  3. UVA-10655 Contemplation! Algebra (矩阵)

    题目大意:给出a+b的值和ab的值,求a^n+b^n的值. 题目分析:有种错误的方法是这样的:利用已知的两个方程联立,求解出a和b,进而求出答案.这种方法之所以错,是因为这种方法有局限性.联立之后会得 ...

  4. (转)RocketMQ源码学习--消息存储篇

    http://www.tuicool.com/articles/umQfMzA 1.序言 今天来和大家探讨一下RocketMQ在消息存储方面所作出的努力,在介绍RocketMQ的存储模型之前,可以先探 ...

  5. UVSLive 6324 求射箭覆盖的期望

    DES:给出n条线段.询问每次射中线段条数的期望. 非常简单.就是每条线段的两端与原点相连的直线之间的夹角和.如果夹角大于pi.就是2pi减去这个角.最后除以总值2pi就是所求的期望. atan2(y ...

  6. Awk 从入门到放弃(4) — Aws 格式化

    转:http://www.zsythink.net/archives/1421 print & printf的区别:printf不带\r\n 在awk当中,格式替换符的数量必须与传入的参数的数 ...

  7. 【剑指offer-12】矩阵中的路径

    题目描述 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径.路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子.如果一条路径经过了矩阵中 ...

  8. 开发工具之play framework

    Play!是一个full-stack(全栈的)Java Web应用框架,包括一个简单的无   状态MVC模型,具有Hibernate的对象持续,一个基于Groovy的模板引擎,以及建立一个现代Web应 ...

  9. java中数组是不是对象?

    [转自知乎]:http://www.zhihu.com/question/26297216 JAVA中的数组是对象吗? public class test { public static void m ...

  10. JSON 数组的创建方式

    procedure TFormDZMD.Button1Click(Sender: TObject); var ja: ISuperObject; begin ja := SA([]); ja.AsAr ...