poj 2828

题目链接

TLE代码:

#include <iostream>
#include <cstdio>


using namespace std;
const int maxn=2e5+10;
struct tr
{
	int val;
	int le,ri;
}tr[maxn<<2];

void build(int l,int r,int rt)
{
	tr[rt].val=-1;
	tr[rt].le=l;
	tr[rt].ri=r;
	if(l==r)
		return ;
	int mid=l+r>>1;
	build(l,mid,rt<<1);
	build(mid+1, r, rt<<1|1);
	
}

void update(int rt, int pos, int& val,int n)//这里的val存的是下一个要修改的值,利用线段树,将位置pos到n的所有结点都向后移一位
{
	if(tr[rt].ri<=n&& tr[rt].le==tr[rt].ri)
	{
		int t=tr[rt].val;
		tr[rt].val=val;
		val=t;
		return;
	}
	if(tr[rt].le>n) return;
	int mid=tr[rt].le+tr[rt].ri>>1;
	if(pos<=mid)
	{
		update(rt<<1,pos,val,n);
		update(rt<<1|1,pos,val,n);
	}
	else if(pos >mid)
		update(rt<<1|1,pos,val,n);
}

void prit(int l, int r,int rt, int& flag)
{
	if(tr[rt].le==tr[rt].ri && tr[rt].ri<=r)
	{
		// cout<<endl;
		// cout<<tr[rt].le<<" "<<tr[rt].ri<<endl;
		if(flag==0) 
		{
			printf("%d",tr[rt].val);
			flag=1;
		}
		else
		{
			printf(" %d",tr[rt].val);
		}
		return;
	}
	int mid=tr[rt].le+tr[rt].ri>>1;
	if(l>mid) 
		prit(l,r,rt<<1|1,flag);
	else if(r<=mid)
		prit(l,r,rt<<1,flag);
	else
	{
		prit(l,r,rt<<1,flag);
		prit(l,r, rt<<1|1,flag);
	}
}

int main()
{
	int n;
	int pos, val;
	while(~scanf("%d",&n))
	{
		build(0, n, 1);
		for(int i=0;i<n;i++)
		{
			scanf("%d%d",&pos, &val);
			update( 1,pos, val,i);
		}
		int w=0;
		prit(0,n-1,1,w );
		printf("\n");
	}
	
	
	return 0;
}

换了种方法:从后面往前走,可以发现最后一个数一定是放在pos位的,然后利用tr[rt].num存放该结点下有多少个空位子,对于倒数第二个数(pos2,val2)放的位置,那么就是第pos2个空位子(可以好好理解下,假如最后一个放的位置在倒数第二个后面还是前面,所放的都是第pos2个空位子的地方),具体看代码

#include <iostream>
#include <cstdio>


using namespace std;
const int maxn=2e5+10;
#define p pair<int, int >
struct tr
{
	int le,ri;
	int num;//表示在[le,ri]中的空位置个数
}tr[maxn<<2];

p su[maxn];
int a[maxn];

void build(int l,int r,int rt)
{
	tr[rt].le=l;
	tr[rt].ri=r;
	tr[rt].num=r-l+1;
	if(l==r)
		return ;
	int mid=l+r>>1;
	build(l,mid,rt<<1);
	build(mid+1, r, rt<<1|1);	
}

void update(int l,int r,int rt,int pos,int val)
{
	tr[rt].num--;
	if(tr[rt].le==tr[rt].ri)
	{
		a[tr[rt].le]=val;
		return;
	}
	int mid=tr[rt].le+tr[rt].ri>>1;
	if(pos<=tr[rt<<1].num)
	{
		update(l,mid,rt<<1,pos,val);
	}
	else 
	{
		pos-=tr[rt<<1].num;
		update(mid+1,r,rt<<1|1,pos,val);
	}
}


int main()
{
	int n;
	int pos, val;
	while(~scanf("%d",&n))
	{
		build(0, n-1, 1);
		for(int i=0;i<n;i++)
		{
			scanf("%d%d",&su[i].first, &su[i].second);
			
		}
		for(int i=n-1;i>=0;i--)
		{
			
			update(0,n-1,1,su[i].first+1,su[i].second);
		}
		for(int i=0;i<n;i++)
		{
			if(i!=n-1)
				printf("%d ",a[i]);
			else
				printf("%d\n",a[i]);
		}
	}
	
	
	return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值