您的位置:首页 > 其它

线段树入门 POJ 2182 Lots Cows

2009-11-27 22:05 447 查看
看别人的思路:

从后往前推,排在最后一头牛比他编号小的数量有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表示此牛已经被删除。

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int n;
int a[8010];
int p[8010];
int f[8010];
int main()
{
scanf("%d",&n);
int i =1;
a[1]=1;
for(i=2;i<=n;i++)
{
scanf("%d",&a[i]);
}
a[1]=0;
for(i=n;i>0;i--)
{
int k = 0;
int j =0;
for(j=1;j<=n;j++)
if(f[j]==0)
{
k++;
if(k==a[i]+1)
break;
}
p[i]=j;
f[j]=1;//dele k-th cow
}
for(i=1;i<=n;i++)
printf("%d/n",p[i]);
}


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

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

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct node
{
int l,r;
int cnt;//在[l,r]区间中的个数
}tree[16*1024];
int save[8010];
int a[8010];
void build(int l,int r,int u)
{
tree[u].l=l;
tree[u].r=r;
tree[u].cnt = r-l+1;
if(l<r)
{
build(l,(l+r)/2,2*u);
build((l+r)/2+1,r,2*u+1);
}
}
void del(int c,int root)
{
if(tree[root].l==tree[root].r)
{
save[++save[0]]=tree[root].l;
tree[root].cnt=0;
return;
}
if(c<=tree[2*root].cnt)
del(c,2*root);
else
del(c-tree[2*root].cnt,2*root+1);
tree[root].cnt--;
}
int main()
{
int n ;
scanf("%d",&n);
int i =0;
a[1]=0;
for(i=2;i<=n;i++)
scanf("%d",&a[i]);
build(1,n,1);
for(i=n;i>=1;i--)
del(a[i]+1,1);
for(i=save[0];i>=1;i--)
printf("%d/n",save[i]);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: