//此题是离散化加线段树。由于点范围较大,所以要离散化,本题由于有些敏感变量一直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; }