poj 2181 (线段树)

来源:互联网 发布:移动数据网怎么转电信 编辑:程序博客网 时间:2024/05/01 03:26

看别人的思路:

从后往前推,排在最后一头牛比他编号小的数量有x头牛,那么最后一头牛的编号必然为x+1。

按照这种思路下去,我们把1-n编号的牛排成一排。把x+1这头牛从里面删除。

假如倒数第二头牛在他前面比他编号小的数量有y头牛,那么就在这1-n删掉了求出来的牛后剩下的第y+1头牛。

方法一:直接搜索(n*n)

p[i]表示第i个应该放的cow的id。

f[i]=0表示此牛还未被删除,f[i]=1表示此牛已经被删除。

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. using namespace std;  
  5. int n;  
  6. int a[8010];  
  7. int p[8010];  
  8. int f[8010];  
  9. int main()  
  10. {  
  11.     scanf("%d",&n);  
  12.     int i =1;  
  13.     a[1]=1;  
  14.     for(i=2;i<=n;i++)  
  15.     {  
  16.         scanf("%d",&a[i]);  
  17.     }  
  18.     a[1]=0;  
  19.     for(i=n;i>0;i--)  
  20.     {  
  21.         int k = 0;  
  22.         int j =0;  
  23.         for(j=1;j<=n;j++)  
  24.                 if(f[j]==0)  
  25.                 {  
  26.                         k++;  
  27.                         if(k==a[i]+1)  
  28.                                 break;  
  29.                 }  
  30.         p[i]=j;  
  31.         f[j]=1;//dele k-th cow  
  32.     }  
  33.     for(i=1;i<=n;i++)  
  34.         printf("%d/n",p[i]);  
  35. }  

方法二:线段树(n*lgn) 

搜索排在第n位的数是几时可用线段树实现 ,对于一个线段树中的所代表的线段[a,b],结点中的数值纪录[a,b]中还有多少人没有被去掉,记为len,所以对于一个在剩余数字队列中排在第n位,看这个人是在一个结点的左子树中还是右子树中。

[cpp] view plaincopy
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <cstring>  
  4. using namespace std;  
  5. struct node   
  6. {  
  7.     int l,r;  
  8.     int cnt;//在[l,r]区间中的个数  
  9. }tree[16*1024];  
  10. int save[8010];  
  11. int a[8010];  
  12. void build(int l,int r,int u)  
  13. {  
  14.     tree[u].l=l;  
  15.     tree[u].r=r;  
  16.     tree[u].cnt = r-l+1;  
  17.     if(l<r)  
  18.     {  
  19.             build(l,(l+r)/2,2*u);  
  20.             build((l+r)/2+1,r,2*u+1);  
  21.     }  
  22. }  
  23. void del(int c,int root)  
  24. {  
  25.         if(tree[root].l==tree[root].r)  
  26.         {  
  27.             save[++save[0]]=tree[root].l;  
  28.             tree[root].cnt=0;  
  29.             return;  
  30.         }  
  31.         if(c<=tree[2*root].cnt)  
  32.             del(c,2*root);  
  33.         else  
  34.                 del(c-tree[2*root].cnt,2*root+1);  
  35.         tree[root].cnt--;  
  36. }  
  37. int main()  
  38. {  
  39.     int n ;  
  40.     scanf("%d",&n);  
  41.     int i =0;  
  42.     a[1]=0;  
  43.     for(i=2;i<=n;i++)  
  44.             scanf("%d",&a[i]);  
  45.     build(1,n,1);  
  46.     for(i=n;i>=1;i--)  
  47.             del(a[i]+1,1);  
  48.     for(i=save[0];i>=1;i--)  
  49.             printf("%d/n",save[i]);  
  50. }  

原创粉丝点击