传送门:POJ 2182
题意:给定一个序列每个数的逆序数(第一个逆序数个数默认为零,不给出),求原序列。
思路:这题和POJ2828有些相似,如果用线段树做基本一样了,都是维护区间内还有几个空位。
但这个题我是用树状数组+二分做的,这样做的核心思想:序列中第n个数的逆序数应该是其逆序数+1,第n个数确定后,以此类推能确定第n-1个数。。。一直到第一个数。
详见代码:
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<math.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<vector>
#include<map>
#define ll long long
#define pi acos(-1)
#define inf 0x3f3f3f3f
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
typedef pair<int,int>P;
const int MAXN=10010;
int n;
int a[MAXN],bit[MAXN],ans[MAXN];//树状数组保存的是哪些数已经出现过了
int sum(int i)
{
int ans=0;
while(i>0)
{
ans+=bit[i];
i-=i&-i;
}
return ans;
}
void add(int i,int x)
{
while(i<=n)
{
bit[i]+=x;
i+=i&-i;
}
}
int binery_search(int k)
{
int l=0,r=n,mid;
while(l<=r)
{
mid=(l+r)>>1;
int temp=sum(mid);
if(mid-1-temp>=k)
r=mid-1;
else
l=mid+1;
}
return r+1;
}
int main()
{
cin>>n;
for(int i=1;i<n;i++)
{
cin>>a[i];
}
for(int i=n-1;i>=0;i--)
{
int id=binery_search(a[i]);
ans[i]=id;
add(id,1);
}
for(int i=0;i<n;i++)
cout<<ans[i]<<endl;
return 0;
}
顺便提一句,这题数据很水,纯暴力也能过。