//此题是离散化加线段树。由于点范围较大,所以要离散化,本题由于有些敏感变量一直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;
}
本文详细介绍了离散化技术及其与线段树结合的使用方法,通过实例展示了如何利用这些算法解决具有挑战性的编程问题。包括离散化过程、线段树构建、更新和查询操作,以及解决实际问题的步骤和技巧。
236

被折叠的 条评论
为什么被折叠?



