poj 2182 Lost Cows (线段树)

30 篇文章 0 订阅
28 篇文章 0 订阅

Lost Cows
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 8838 Accepted: 5657

Description

N (2 <= N <= 8,000) cows have unique brands in the range 1..N. In a spectacular display of poor judgment, they visited the neighborhood 'watering hole' and drank a few too many beers before dinner. When it was time to line up for their evening meal, they did not line up in the required ascending numerical order of their brands.  

Regrettably, FJ does not have a way to sort them. Furthermore, he's not very good at observing problems. Instead of writing down each cow's brand, he determined a rather silly statistic: For each cow in line, he knows the number of cows that precede that cow in line that do, in fact, have smaller brands than that cow.  

Given this data, tell FJ the exact ordering of the cows.  

Input

* Line 1: A single integer, N  

* Lines 2..N: These N-1 lines describe the number of cows that precede a given cow in line and have brands smaller than that cow. Of course, no cows precede the first cow in line, so she is not listed. Line 2 of the input describes the number of preceding cows whose brands are smaller than the cow in slot #2; line 3 describes the number of preceding cows whose brands are smaller than the cow in slot #3; and so on.  

Output

* Lines 1..N: Each of the N lines of output tells the brand of a cow in line. Line #1 of the output tells the brand of the first cow in line; line 2 tells the brand of the second cow; and so on.

Sample Input

5
1
2
1
0

Sample Output

2
4
5
3
1

Source


这道题算是我的线段树处女题吧,感觉线段树的应用真心的广啊,对线段树还没达到那种灵活运用的地步,线段树的应用范围比树状数组还要广一些,这道题也可以用树状数组来做,树状数组和线段树要掌握好啊,比较重要,要达到能够灵活运用!!
对这种英语题还是比较无感啊,开始对题意都理解不了,英语能力还有待加强,刚开始看这道题的样例输入,看5个输入,但是只有4个输入,开始都没看懂,其实这里是一个隐含条件,乱序排的第一个,前面没有元素了,所以前面比它小的就没有,所以第一个就是0,所以样例就应该是5(0,1,2,1,0),看了好久,才总算好久把题意看懂,然后还没找到和线段树的切入点;
题意就是:给你乱序排成一列的牛,给你每头牛前面有多少头牛比它的编号小,求排队后从前往后数,每头牛的编号;
参考了大神的思路,首先建立一颗线段树,然后从后往前扫描,遇到序号i,说明是剩余序号的i+1号,然后就借助线段树查找,看一个区间内的数字能否满足要找的那个数成为i+1,能就递归左子树,不能就递归右子树,直到叶子节点,叶子节点的值就是原来的编号
下面是ac的代码;
#include <stdio.h>
#define N 8002
int num[N],ans[N];
struct segment
{
    int l,r,len;
}s[N];
void build(int root,int l,int r)//建立树
{
   s[root].l=l;
   s[root].r=r;
   s[root].len=r-l+1;//线段的区间(按照题意)
   if(l==r)return;
   build(2*root,l,(l+r)/2);
   build(2*root+1,(l+r)/2+1,r);
}
int query(int root,int k)//查找线段树
{
    s[root].len--;//每查找一次,区间就减1,说明找到了一个编号,就删除那个节点;
    if(s[root].l==s[root].r) return s[root].l;//说明找到叶子节点
    else if(k<=s[2*root].len)
    {return query(2*root,k);}//递归左子树
    else
    {return query(2*root+1,k-s[2*root].len);}//递归右子树
}
int main()
{
   int n;
   scanf("%d",&n);
   for(int i=2;i<=n;i++)
     scanf("%d",&num[i]);
    num[1]=0;//第一个编号为0;
    build(1,1,n);
    for(int i=n;i>=1;i--)//倒序
        ans[i]=query(1,num[i]+1);
    for(int i=1;i<=n;i++)
        printf("%d\n",ans[i]);
    return 0;
}
这道题还可以用数组数组做,换一种思路,明天再做,(未完待续。。)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值