当前位置: 代码迷 >> 综合 >> POJ 2182 Lost Cows树状数组 *
  详细解决方案

POJ 2182 Lost Cows树状数组 *

热度:24   发布时间:2023-09-23 07:41:02.0

题目地址:http://poj.org/problem?id=2352

a[i]表示i排第几

每个位置i代表,1~i有几个比i小的数

可以从倒着来放数字,最后一个数n就是a[n]+1,因为只要前面有a[n]个比他小的数就好了,那么就是从小到大第a[n]个数

倒数第二个数也是这样,因为只要考虑在他前面的数

所以基本算法就是在待选的数中选第a[i]个放在i的位置上,当然要从后往前放


用树状数组+二分查找可以更快找出第a[i]个数

a[i]表示第i为放了没,所以一开始a[1~n]=1;

那么Sum(i)就表示1~i个数还有几个没放,即排第几

查出来后就将a[i]表示为0,表示已经用了


#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int maxn=8000+5;
int lowbit[maxn],C[maxn],a[maxn],ans[maxn];
void init(int n)
{for(int i=1;i<=n;i++)lowbit[i]=i&(-i);
}
int Sum(int p) //a[1]+a[2]+....+a[p] 
{int sum=0;while(p>0){sum+=C[p];p-=lowbit[p];}return sum;
}
void Modify(int p,int val,int n)
{while(p<=n){C[p]+=val;p+=lowbit[p];}
}
int BinarySearch(int v,int n) //查找第v的数 
{int L=0,R=n;while(R-L>1)  //1~n中选个排第v个的数字 {int mid=(L+R)/2;int p=Sum(mid);   //Sum等于小于mid排第几在未用的数字中 if(p>=v) R=mid;else     L=mid;}return R;
}
int main()
{int n;cin>>n;init(n);Modify(1,1,n);for(int i=2;i<=n;i++) cin>>a[i],Modify(i,1,n);  //1~n 个数,每个位置待选 for(int i=n;i>=1;i--) {ans[i]=BinarySearch(a[i]+1,n);  //查找第a[i]+1的数字 Modify(ans[i],-1,n);       //标识用掉了 }for(int i=1;i<=n;i++) cout<<ans[i]<<endl;return 0;
}




  相关解决方案