uva 11525 Permutation
2014-04-29 17:28
204 查看
题目:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2520
找个简单的例子,k=3的时候:
2! 1! 0!
0 0 0 0 123
1 0 1 0 132
2 1 0 0 213
3 1 1 0 231
4 2 0 0 312
5 2 1 0 321
n S1 S2 S3
发现木有,有规律! 从最高位开始,第i位是使sum(1,j)==(Si + 1) 的最小j,sum只针对没用过的数。
所以可以用树状数组加二分,二分j;
也可以用线段树,单点存区间数字个数和,每次查询一个数,和节点的个数和比较决定往左还是往右,求得答案后,再单点更新。
找个简单的例子,k=3的时候:
2! 1! 0!
0 0 0 0 123
1 0 1 0 132
2 1 0 0 213
3 1 1 0 231
4 2 0 0 312
5 2 1 0 321
n S1 S2 S3
发现木有,有规律! 从最高位开始,第i位是使sum(1,j)==(Si + 1) 的最小j,sum只针对没用过的数。
所以可以用树状数组加二分,二分j;
也可以用线段树,单点存区间数字个数和,每次查询一个数,和节点的个数和比较决定往左还是往右,求得答案后,再单点更新。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<t;i++) #define clr(a) memset(a,0,sizeof(a)) #define N 50005 int t,k; int a,c ; bool vis ; inline int lowbit(int x){ return x&(-x); } inline void add(int x,int val){ while(x<=k) c[x]+=val,x+=lowbit(x); } inline int sum(int x){ int ans=0; while(x>0) ans+=c[x],x-=lowbit(x); return ans; } inline int binarySearch(int num){ int s=1,t=k,mid; while(s<=t){ mid=(s+t)>>1; int ret=sum(mid); if(ret==num && !vis[mid]) return mid; if(ret<num) s=mid+1; else t=mid-1; } return -1; } int main(){ scanf("%d",&t); while(t--){ scanf("%d",&k); clr(c);clr(vis); rep(i,1,k+1) add(i,1); rep(i,0,k){ scanf("%d",&a);a++; int b=binarySearch(a); vis[b]=1; add(b,-1); printf("%d",b); if(i<k-1) printf(" "); else printf("\n"); } } return 0; }
相关文章推荐
- 在C++ MFC中Single document和Dialog based有什么具体的区别?
- JAVA字符串格式化-String.format()的使用(转)
- 【转载】实用VC++6.0插件
- VS2008 编译 libpng库
- int *p=&a
- VB.NET小结——再聊面向对象
- __declspec(dllimport)的作用
- ubuntu-root\ls...
- VB.NET小结——再聊面向对象
- 深入理解JVM性能调优
- nyoj 547 优先队列
- Excel函数大全
- mysql算两个日期之间的工作日
- 网页自动播放声音
- PHP获取IP地址及根据IP判断城市实现城市切换或跳转
- 关于无标题栏窗口拖动的问题
- arguments.callee的临时指向特性
- 如何用Ajax传一个数组数据
- nyoj 547 优先队列
- CATransition使用导致内存泄漏