poj 2182 树状数组
这题对于O(n^2)的算法有很多,我这随便贴一个烂的,跑了375ms。
#include<iostream> #include<algorithm> using namespace std; int mat[8008]; int main() { int i,j,t,n; scanf("%d",&n); mat[0]=1; for(i=1;i<n;i++) { scanf("%d",&t); mat[i]=t+1; for(j=0;j<i;j++) if(mat[j]>=mat[i]) { mat[j]++;} } for(i=0;i<n;i++) printf("%d\n",mat[i]); return 0; }
还是来看树状数组的解法。我们从后面往见面看,假设第i个牛前面有Rank[i]个牛标号比他小,由此很容易得出最后一个牛的编号一定是Rank[n]+1。我们将最后一个牛去掉后,剩下n-1牛时,对于第n-1个牛的道理是一样的,只不过不同的是Rank[n-1]+1之前有多少个牛已经不存在了,即已经确定位置。我们就用树状数组保存被去掉的牛个数,C[i]表示标号i之前已经有多少个牛确定位置。那么我们每次就是要找某个数k,使得k-C[k]==Rank[i]+1。这就是第i个牛的确定位置。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<cmath> #define Maxn 8010 #define inf 0x7fffffff #define lowbit(x) (x&(-x)) using namespace std; int C[Maxn],n,Rank[Maxn],ans[Maxn]; void init() { memset(C,0,sizeof(C)); } int Sum(int pos) { int sum=0; while(pos>0) { sum+=C[pos]; pos-=lowbit(pos); } return sum; } void update(int pos,int num) { while(pos<=n) { C[pos]+=num; pos+=lowbit(pos); } } int getPos(int i) { int l=1,r=n,temp; while(l<r) { int mid=(l+r)>>1; temp=mid-Sum(mid); if(temp<i) l=mid+1; else r=mid; } return l; } int main() { int i,j,a,b,c; while(scanf("%d",&n)!=EOF) { init(); for(i=2;i<=n;i++) scanf("%d",&Rank[i]); Rank[1]=0; for(i=n;i>=1;i--) { int pos=getPos(Rank[i]+1); ans[i]=pos; update(pos,1); } for(i=1;i<=n;i++) printf("%d\n",ans[i]); } return 0; }