POJ 2528 Mayor's posters 线段树区间更新+离散化

Description

The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral posters at all places at their whim. The city council has finally decided to build an electoral wall for placing the posters and introduce the following rules: 
  • Every candidate can place exactly one poster on the wall. 
  • All posters are of the same height equal to the height of the wall; the width of a poster can be any integer number of bytes (byte is the unit of length in Bytetown). 
  • The wall is divided into segments and the width of each segment is one byte. 
  • Each poster must completely cover a contiguous number of wall segments.

They have built a wall 10000000 bytes long (such that there is enough place for all candidates). When the electoral campaign was restarted, the candidates were placing their posters on the wall and their posters differed widely in width. Moreover, the candidates started placing their posters on wall segments already occupied by other posters. Everyone in Bytetown was curious whose posters will be visible (entirely or in part) on the last day before elections. 
Your task is to find the number of visible posters when all the posters are placed given the information about posters' size, their place and order of placement on the electoral wall. 

Input

The first line of input contains a number c giving the number of cases that follow. The first line of data for a single case contains number 1 <= n <= 10000. The subsequent n lines describe the posters in the order in which they were placed. The i-th line among the n lines contains two integer numbers l i and ri which are the number of the wall segment occupied by the left end and the right end of the i-th poster, respectively. We know that for each 1 <= i <= n, 1 <= l i <= ri <= 10000000. After the i-th poster is placed, it entirely covers all wall segments numbered l i, l i+1 ,... , ri.

Output

For each input data set print the number of visible posters after all the posters are placed. 

The picture below illustrates the case of the sample input. 

Sample Input

1
5
1 4
2 6
8 10
3 4
7 10

Sample Output

4
  题目意思大概是含1*10^7个单位长度的板上贴海报,每个海报占得地方是l~r的单位长度,因为后面贴的海报可能遮住前面贴的海报,求最后可以露出部分或者全部的海报的数目。
  先推荐一篇介绍离散化的文,http://www.cppblog.com/MiYu/archive/2010/10/15/129999.aspx
  注意到板含有10^7个单位,若是简单的线段树区间更新会超内存,但是海报的数目只有10000个,这时候就要用离散化进行处理。原来的板的最小区间含一个单位,运用离散化将板分成由几个更大的区间组成的板。
  一开始我的离散化想法是把所有的l,r看成端点,把所有区间划分成几部分,例如上例就化成1~2,2~3,3~4,4~6,6~7,7~8,8~10,10~+∞这几个区间,提交结果WA,发现l是可以等于r的- -,那样像这样区间的划分就不成立了。
    那么就转为将所有的区间离散化为x[1]=1,x[2]=2,x[3]=3,x[4]=4,x[5]=6,x[6]=7,x[7]=8,x[8]=10这几个点,线段树的最大区间由1~10变成了1~8,第一张海报覆盖了1~4,第二张覆盖了2~5,第三张覆盖了7~8……
   但是这样有个问题,要是有三张海报,第一张是1 10,第二张是1~4,第三张是6~10,离散化结果第一张覆盖了1~8,第二张覆盖了1~4,第二张覆盖了5~8,结果就只露出来两张海报,实际第一张也有5这个地方是露出来的。所以还需要一个在相差大于1相邻点间插入一个值的操作。
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
#define maxn 40000+10
typedef struct
{
	int l,r,change;
}node;
node num[maxn<<2];
int vis[10010];
void build(int pos,int L,int R)
{
	num[pos].change=0;
	num[pos].l=L;
	num[pos].r=R;
	if(L==R)
	return;
	int mid=(L+R)>>1;
	build(pos<<1,L,mid);
	build(pos<<1|1,mid+1,R);
}
void pushdown(int pos,int L,int R)
{
	if(num[pos].change!=0)
	{
		num[pos<<1].change=num[pos<<1|1].change=num[pos].change;
		num[pos].change=0;
	}
}
void update(int pos,int L,int R,int ul,int ur,int val)
{
	if(ul>R||ur<L)
	return ;
	if(ul<=L&&ur>=R)
	{
		num[pos].change=val;
		return ;
	}
	else
	{
		pushdown(pos,L,R);
		int mid=(L+R)>>1;
		update(pos<<1,L,mid,ul,ur,val);
		update(pos<<1|1,mid+1,R,ul,ur,val);
	}
}
void query(int pos,int L,int R)
{
	if(L==R)
	{
		vis[num[pos].change]=1;
		return ;
	}
	else
	{
		pushdown(pos,L,R);
		int mid=(L+R)>>1;
		query(pos<<1,L,mid);
		query(pos<<1|1,mid+1,R);
	}
}
int main()
{
	int t,n,x[40010],i,xcount,poster[10010][2],add,l,r,ans;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		ans=xcount=0;
		memset(x,0,sizeof(x));
		memset(vis,0,sizeof(vis));
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&poster[i][0],&poster[i][1]);
			x[xcount++]=poster[i][0];
			x[xcount++]=poster[i][1];
		}
		sort(x,x+xcount);
		xcount=unique(x,x+xcount)-x;                 //讲所有端点排序并去重复 
		add=xcount;             
		for(i=1;i<xcount;i++)
		{
			if(x[i]!=x[i-1]+1)
			x[add++]=x[i-1]+1;                      //在每个相邻端点相差大于1的点间加一个点 
		}
		sort(x,x+add);
		xcount=unique(x,x+add)-x;                  //加入新坐标后的坐标数组 
		build(1,1,xcount);
		for(i=1;i<=n;i++)
		{
			l=lower_bound(x,x+xcount,poster[i][0])-x+1;         
			r=lower_bound(x,x+xcount,poster[i][1])-x+1;      //查出左右端点的次序 
			update(1,1,xcount,l,r,i);                        //更新线段树,每个海报的对应区间标记成海报次序 
		}
		query(1,1,xcount);
		for(i=1;i<=n;i++)
		{
			if(vis[i])
			ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}



    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在MATLAB中实现机械臂的仿真可以使用Robotic System Toolbox来进行。Robotic System Toolbox包含许多工具和函数,可以实现机械臂的建模、控制和仿真。 首先,需要定义机械臂的模型。可以使用robotics.RigidBodyTree类来创建机械臂的刚体树结构。通过添加关节和刚体可以构建机械臂的结构。可以使用函数robotics.RigidBody来创建刚体,并使用函数robotics.Joint来创建关节。 接下来,可以使用robotics.RigidBodyTree类中的函数来定义机械臂的初始状态。可以设置每个关节的初始位置和速度。 然后,可以使用robotics.RigidBodyTree类中的函数来进行机械臂的运动控制。可以使用函数robotics.InverseKinematics来实现逆运动学,根据目标位置和姿态来求解关节角度。可以使用函数robotics.CartesianTrajectory来生成机械臂的轨迹,指定起始和目标位置以及运动时间。 最后,可以使用robotics.RigidBodyTree类中的函数来进行机械臂的仿真。可以使用函数robotics.Rate来指定仿真的频率,然后使用循环来更新机械臂的状态和控制输入,实现机械臂的运动。 以下是一个基本的机械臂仿真的示例代码: ```matlab % 创建机械臂模型 robot = robotics.RigidBodyTree; % 添加机械臂的关节和刚体 % 设置机械臂的初始状态 % 运动控制 % 仿真循环 % 绘制机械臂的运动轨迹 ``` 在实际的机械臂仿真中,可能还需要考虑机械臂的动力学、碰撞检测和路径规划等问题。可以使用Robotic System Toolbox中的其他工具和函数来处理这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值