题解:UVA11525 Permutation
UVA11525 题解
题面
前置知识
题意很简单,就是求长度为 n 的数组 a 在全部 n 的排列中按字典序排序的排名。
先那一组数据来手玩:
求 4 2 3 5 1
的排名。
- 第一位是 4,在这这个排列中,还会有以 1,2,3 作为第一位,所以它会增加 3×(5−1)!=72 的排名。
- 第二位是 2,在以
4
为第一位的排列中,还会有 1 作为第二位,所以它会增加 1×(5−2)!=6 的排名。 - 第三位是 3,在以
4 2
为前两位的排列中,还会有 1 作为第三位,所以他会增加 1×(5−3)!=2 的排名。 - 第四位是 5,在以
4 2 3
为前三位的排列中,还会有 1 作为第四位,所以它会增加 1×(5−4)!=1 的排名。 - 第五位无需考虑
所以,该排列的排名为 72+6+2+1+1=82 名,记得最后要加 1,因为我们算的是该排列前面有多少个排列。
形式化的,记 si←n∑j=i+1[aj<ai],则 a 的排名就为 n∑i=1si×(n−i)!。
如果暴力求这个数组的话是 O(n2),会超时,所以考虑用树状数组优化,就可以达到 O(nlogn),原理和树状数组求逆序对一样。
思路
把本题的题面对比下正向康托展开发现式子一模一样,所以也就知道这题中的 Si 就是 n∑j=i+1[aj<ai],所以问题就转化成了已知每个数后面有几个小于自己的数,求这个序列。
这个很好办,用树状数组加二分,我们可以从前往后一个一个确定 a。
Si 就为比 i 小并且未被确定的数的个数。
在逐步确定 a 过程中,对于每个 i∈{1,2,⋯,n},比 i 小并且未被确定的数的个数满足单调性,于是就可以二分求 ai,然后标上 ai 已被标记(在树状数组中把 ai 位置减一)。
时间复杂度为 O(nlog2n),用线段树上二分可以优化到 O(nlogn),但是笔者太懒(菜)了,只打了树状数组(反正能过就行)。
实现细节
一定要记得每一行的最后不能打空格!!!
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int MN=5e4+5;
ll n,t[MN],a[MN];
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
ll lowbit(ll x){return x&-x;}
void change(ll x, ll v){while(x<=n){t[x]+=v;x+=lowbit(x);}}
ll query(ll x){ll res=0;while(x){res+=t[x];x-=lowbit(x);}return res;}
ll get(ll x){
ll l=1,r=n+1,res;
while(l<r){
ll mid=l+r>>1,num=query(mid-1);
if(num>x) r=mid;
else l=mid+1;
}
return l-1;
}
void solve(){
for(int i=1; i<=n; i++) t[i]=0;
n=read();
for(int i=1; i<=n; i++) change(i,1);
for(int i=1; i<=n; i++){
ll x=read();
a[i]=get(x);
change(a[i],-1);
}
for(int i=1; i<=n; i++){
write(a[i]);
if(i!=n) putchar(' ');
}putchar('\n');
}
int main(){
ll T=read();while(T--) solve();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!