题意:http://poj.org/problem?id=2828
告诉你第i个人来他排在第几个位置和第i个人他自己的价值。让你输出这个队列最后的排列顺序(用价值表示)。
解:
最可爱的方法是用个数组模拟,但是这样子队伍移动地太慢了。
其次就是用链表了,这样尽管插得快,但是找得太慢了。
这样,我们就想到了我们可爱的线段树数据结构。
从后往前做是这个意思:拿样例来说。
4 0 77 1 51 1 33 2 6969肯定在第三个位置。
69插完后,33要在第1 + 1个空位上。
33插完后,51要在第1 + 1个空位上。
51插完后,77要在第0 + 1个空位上。
用一棵线段树去维护每个区间有多少空位,查询的时候返回第几个空位的位置。
这题难的不是代码,而是想法。
从后往前的时候,若a要在第3个位置插入,那么意味着前面肯定有两个位置没人。
从前往后的时候,若a要在第3个位置插入,那么意味着前面两个位置一定有人。
/*
Pro: 0
Sol:
date:
*/
#define maxn 200010
#define lson l,m,rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define havem int m = (l + r) >> 1
#include <cstdio>
using namespace std;
int ans[maxn],val[maxn],pos[maxn],sum[maxn << 2],n;
void build(int l , int r, int rt){
sum[rt] = r - l + 1;
if(l == r) return;
havem;
build(lson); build(rson);
}
int getpos(int pos, int l, int r, int rt){//返回的是第pos[] + 1的空位的下标
sum[rt] --;
if(l == r) {
return l;
}havem;
if(sum[ls] >= pos) return getpos(pos,lson);
else return getpos(pos - sum[ls],rson);//就在右儿子里面去找pos - sum[ls]
}
int main(){
while(~scanf("%d",&n)){
for(int i = 1; i <= n; i ++)
scanf("%d%d",&pos[i],&val[i]);
build(1,n,1);
for(int i = n; i >= 1; i --){//从后往前依次插入
ans[getpos(pos[i] + 1, 1,n,1)] = val[i];
}
for(int i = 1;i < n;i ++){
printf("%d ",ans[i]);
}printf("%d\n",ans[n]);
}
return 0;
}
树状数组(贴的):
解题报告:
本题的算法是利用线段树进行倒推。基本思想是拿一个N个1的序列,从最后一次插入开始倒推。
设当前插入的是Pos Val,那么找到从左边数第Pos + 1个1的位置就是最终需要插入Val的位置,
然后把那个1改成0。 这里找pos + 1个1的位置的方法很是奇葩。
#include<cstdio>
#include<cstring>
const int MAXN = 200010;
int c[MAXN];
int pos[MAXN],val[MAXN],ans[MAXN];
int N;
inline int lowbit(int x){return x&(-x);}
void dec(int p)
{
while(p<=N)
{
c[p]--;
p+=lowbit(p);
}
}
int getK(int K)
{
int ans = 0,cnt=0;
for(int i=18;i>=0;i--)//i>=0
{
ans+=(1<<i);
if(ans>=N||cnt+c[ans]>=K)ans-=(1<<i);
else cnt+=c[ans];
}
return ans+1;
}
int main()
{
for(;~scanf("%d",&N);)
{
for(int i=1;i<=N;i++)
{
scanf("%d%d",&pos[i],&val[i]);
c[i]=lowbit(i);
}
for(int i=N;i;i--)
{
int pp=getK(pos[i]+1);
ans[pp]=val[i];
dec(pp);
}
for(int i=1;i<=N;i++)
printf("%d ",ans[i]);
puts("");
}
return 0;
}