poj2528

 

//此题是离散化加线段树。由于点范围较大,所以要离散化,本题由于有些敏感变量一直TLE,不知道为什么

#include<iostream>

#include<algorithm>

#include<cstdio>

using namespace std;

 

struct Tree

{

int l,r;

int col;

}a[100050];

int used[20010];

struct Node

{

int point,num;

bool operator<(const Node &other)const

{

return point<other.point;

}

}seg[30020];

 

int n,pos[20001][2],cnt;

 

void constrate(int pos,int l,int r)//建树

{

a[pos].col=0;a[pos].l=l;a[pos].r=r;

if(l!=r)

{

int mid=(l+r)>>1;

constrate(2*pos,l,mid);

constrate(2*pos+1,mid+1,r);

}

}

 

void insert(int p,int l,int r,int c)//更新插入,注意只在叶子节点才表示颜色,其他的都是0,这样方便后面计数

{

int mid;

if(a[p].l==l&&a[p].r==r)

{

a[p].col=c;

return;

}

if(a[p].col>0&&a[p].col!=c)

{

a[2*p].col=a[p].col;

a[2*p+1].col=a[p].col;

a[p].col=0;

}

mid=(a[p].l+a[p].r)>>1;

if(r<=mid)

insert(2*p,l,r,c);

else if(l>mid)

insert(2*p+1,l,r,c);

else

{

insert(2*p,l,mid,c);

insert(2*p+1,mid+1,r,c);

}

}

 

void SearchC(int pos)//计数

{

   if(a[pos].col!=0)

   {

      if(!used[a[pos].col])

      {

         used[a[pos].col]=1;

         cnt++;

      }

      return ;

   }

   SearchC(pos*2);

   SearchC(pos*2+1);

}

 

 

int main()

{

int t,i;

while(scanf("%d",&t)!=EOF)

{

while(t--)

{

cnt=0;

scanf("%d",&n);

memset(used,0,sizeof(used));

for(i=0;i<n;i++)//经典的离散化,学习之。

{

scanf("%d%d",&pos[i][0],&pos[i][1]);

//li san hua

seg[i*2].point=pos[i][0];

seg[i*2].num=-(i+1);

seg[i*2+1].point=pos[i][1];

seg[i*2+1].num=i+1;

}

sort(seg,seg+2*n);

int mm=1,tmp=seg[0].point;

for(i=0;i<2*n;i++)

{

if(seg[i].point!=tmp)

{

mm++;

tmp=seg[i].point;

}

if(seg[i].num<0)

pos[-seg[i].num-1][0]=mm;

else

pos[seg[i].num-1][1]=mm;

}

constrate(1,1,mm);

for(i=0;i<n;i++)

{

insert(1,pos[i][0],pos[i][1],i+1);

}

SearchC(1);

printf("%d/n",cnt);

}

}

return 0;

}

 

 

 

转一个不用线段树的,直接离散化,这个也很经典啊。

/*
算法:离散化+暴力
	首先输入所有线段,将它的起点终点排序,得到离散化的点
	将离散化的点从头到尾走一遍,得到每条线段对应的离散点编号
	对每条线段,更新离散点的上的颜色
*/

#include <stdio.h>
#include <memory.h>
#include <stdlib.h>
#define MAX 10020

struct poster{
	int start;
	int end;
}l[MAX];

int posters[MAX][2];

struct point{ //离散点
	int pos;
	int colour;  //对应的
}p[2*MAX];

int cmp(const void* a, const void* b){
	struct point*p = (struct point*)a;
	struct point*q = (struct point*)b;
	return p->pos - q->pos;
}

int n;
int colour[2*MAX]; //离散点的颜色
int used[MAX]; //出现过的海报颜色

int main(){
	int out;
	scanf("%d",&out);
	while(out--){
		memset(l,0,sizeof(l));
		memset(posters,0,sizeof(posters));
		memset(colour, -1, sizeof(colour));
		memset(used,0,sizeof(used));

		scanf("%d",&n);
		int i,counter=0;
		for(i=0; i<n; i++){
			scanf("%d%d",&posters[i][0],&posters[i][1]);
			p[counter].pos = posters[i][0];
			p[counter++].colour = -i;
			p[counter].pos = posters[i][1];
			p[counter++].colour = i;
		}
		//离散化
		qsort(p,counter,sizeof(point),cmp);
		int real_point=0;
		int last_pos = -1; //与所有点都不同
		for(i=0; i<counter; i++){
			if(last_pos != p[i].pos) real_point++, last_pos = p[i].pos;
			if(p[i].colour < 0 ) l[-p[i].colour].start = real_point-1; //离散点的编号
			else l[p[i].colour].end = real_point-1;
		}

		for(i=0; i<n; i++)
			for(int j=l[i].start; j<= l[i].end; j++)
				colour[j] = i;
		int ans=0;
		for(i=0; i<real_point; i++)
			if(!used[colour[i]]) ans++,used[colour[i]] = true;

			printf("%d/n",ans);

	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值