POJ 2828 Buy Tickets 线段树
题意:给出一些人和每个人的入队时在队列的位置。每个人都有一个值val,输出俺顺序输出队列的val,数据量 200000
如果用链表肯定超时,于是乎,用二叉树,but TLE了,才醒悟过来,如果二叉树是个左斜树或右斜树不就跟链表复杂度一样的么。。。
百度是个好东西,原来是线段树,不管什么数据量,可以达到logN,不过题目一般都会让人动脑子,要会转化等等,该题有个小特点,最后插入的数的位置,一定是最终位置,
所以要从后往前放入线段树。最后自己写了一组数据死活过不了,一提交AC,系统有问题?还真不是,那是一组不靠谱的错误数据。。。囧,写数据也要合理才行
每个线段有一个num值,记录该区间可以放几个数
根据数的序号把数加入线段树,之后,这个位置所在的区间可以放得数就减少一个,上推。。。整个区间可以放得数个数也减少一个
代码:
/*
线段树
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#define nMAX 200015
using namespace std;
struct Tree
{
int l,r,num;
}tree[nMAX*4];
struct Node
{
int val,id;
}node[nMAX];
int n,mark,ans[nMAX];
void create(int l,int r,int u)
{
tree[u].num=r-l+1;
tree[u].l=l, tree[u].r=r;
if(l==r)
return ;
int mid=(l+r)/2;
create(l,mid,2*u);
create(mid+1,r,2*u+1);
}
void update(int u)
{
tree[u].num--;
if(tree[u].l==tree[u].r)
{ans[tree[u].l]=node[mark].val;return;}
if(node[mark].id<=tree[2*u].num) update(2*u);
else
{
node[mark].id-=tree[2*u].num;
update(2*u+1);
}
}
int main()
{
int i,j;
while(~scanf("%d",&n))
{
for(i=1;i<=n;i++)
{
scanf("%d%d",&node[i].id,&node[i].val);
node[i].id++;
}
create(1,n,1);
for(i=n;i>=1;i--)
{
mark=i;
update(1);
}
for(i=1;i<=n;i++)
{
if(i==1)printf("%d",ans[i]);
else printf(" %d",ans[i]);
}
printf("\n");
}
return 0;
}

浙公网安备 33010602011771号