HDU1027题解

http://acm.hdu.edu.cn/showproblem.php?pid=1027

【题意】就是求一个第m小的数列,这里的大小就当是以n+1进制的数字比较;

【题解】我先求出需要改变的起点开始,判断后面每一位的数需要改变的值。最后就按前面求出的值处理(我用线段树查找)。


#include<cstdio>
#include<algorithm>
#include<cstdlib>
using namespace std;
int n,m,f[4001],i,w[1001],u[1001];
void tt(int x,int z,int y,int t)
{
	int j;
	for(j=1;j<=z;j++)if(j*t>=y)break;
	u[x]=--j;
	if(x<i)tt(x+1,z-1,y-j*t,t/(z-1));
}
//线段树
//建树 
void establish(int p,int x,int y)
{
	if(x==y){f[p]=1;return;}
	int mid=(x+y)/2;
	establish(p*2,x,mid);
	establish(p*2+1,mid+1,y);
	f[p]=f[p*2]+f[p*2+1];
}
//维护 
inline void keep(int x)
{
	while(x>=1)f[x]--,x>>=1;
}
//查找 
int find(int p,int z,int x,int y)
{
	if(y==x){keep(p);return w[x];}
	int mid=(x+y)/2;
	if(f[p*2]>=z)return find(p*2,z,x,mid);
	 else return find(p*2+1,z-f[p*2],mid+1,y);
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		int t=1;
		for(i=1;i<=n;i++)
		  if(t>m)break;else t*=i;	
		i--;if(i!=0)t/=i;
		tt(1,i,m,t);
		if(n-i>=1)
			{
				printf("%d",1);
				for(int j=2;j<=n-i;j++)printf(" %d",j);
			}
		//这以前一直是在求需要改变的量; 
		int k=0;
		if(n-i>=1)printf(" %d",u[1]+n-i+1);
			else printf("%d",u[1]+n-i+1);
		for(int j=n-i+1;j<=n;j++)
		if((u[1]+n-i+1)!=j)w[++k]=j;
		sort(w+1,w+1+k);//排序; 
		if(k>=1)
		{
				establish(1,1,k);
				for(int j=2;j<=i;j++)printf(" %d",find(1,u[j]+1,1,k));	
		}
		printf("\n");
	}
	return 0;
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值