大致题意:
有一面墙,被等分为1QW份,一份的宽度为一个单位宽度。现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW。后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报。现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报
线段树就不说了》》主要是离散化怎么处理。。。
转: 离散化就是压缩区间,使原有的长区间映射到新的短区间,但是区间压缩前后的覆盖关系不变。举个例子:有一条1到10的数轴(长度为9),给定4个区间[2,4] [3,6] [8,10] [6,9],覆盖关系就是后者覆盖前者,每个区间染色依次为 1 2 3 4。现在我们抽取这4个区间的8个端点,2 4 3 6 8 10 6 9然后删除相同的端点,这里相同的端点为6,则剩下2 4 3 6 8 10 9对其升序排序,得2 3 4 6 8 9 10然后建立映射2 3 4 6 8 9 10↓ ↓ ↓ ↓ ↓ ↓ ↓1 2 3 4 5 6 7那么新的4个区间为 [1,3] [2,4] [5,7] [4,6],覆盖关系没有被改变。新数轴为1到7,即原数轴的长度从9压缩到6,显然构造[1,7]的线段树比构造[1,10]的线段树更省空间,搜索也更快,但是求解的结果却是一致的。 离散化时有一点必须要注意的,就是必须先剔除相同端点后再排序,这样可以减少参与排序元素的个数,节省时间。
User: 1013101127
Memory: 2180K Time: 610MS
Language: G++ Result: Accepted
Source Code
#include <iostream>
#include <string>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int cas;
int n;
int logo[100008][3];
struct poit
{
int pp;
int num;
}mem[100400*3];
int f[100008];
int ans=0;
bool cmp(poit a,poit b)
{
return a.num<b.num;
}
struct node
{
int color;
int l;
int r;
}p[100009];
void built(int t,int lc,int rc)//建树
{
p[t].l=lc;
p[t].r=rc;
p[t].color=0;
if(lc==rc)return ;
built(2*t,lc,(lc+rc)/2);
built(2*t+1,(lc+rc)/2+1,rc);
}
void change(int t,int lc,int rc,int col)//更新各点
{
if(p[t].l==lc&&p[t].r==rc)
{
p[t].color=col;
return ;
}
if(p[t].color>0&&p[t].color!=col)
{
p[2*t].color=p[2*t+1].color=p[t].color;
p[t].color=0;
}
int mid=(p[t].l+p[t].r)/2;
if(rc<=mid)
change(2*t,lc,rc,col);
else if(lc>mid)
change(2*t+1,lc,rc,col);
else
{
change(2*t,lc,mid,col);
change(2*t+1,mid+1,rc,col);
}
}
void query(int t)//查找
{
if(p[t].color!=0)
{
if(!f[p[t].color])
{
f[p[t].color]=1;
ans++;
}
return ;
}
query(2*t);
query(2*t+1);
}
int main()
{
cin>>cas;
while(cas--)
{
cin>>n;
for(int i=0;i<n;i++)
{
cin>>logo[i][0]>>logo[i][1];
mem[i*2].pp=-(i+1);
mem[i*2].num=logo[i][0];
mem[i*2+1].pp=(i+1);
mem[i*2+1].num=logo[i][1];
}
sort(mem,mem+2*n,cmp);
int tmp=mem[0].num;
int sum=1;
for(int i=0;i<2*n;i++)
{
if(mem[i].num!=tmp)
{
sum++;
tmp=mem[i].num;
}
if(mem[i].pp<0)
{
logo[-mem[i].pp-1][0]=sum;
}
else
{
logo[mem[i].pp-1][1]=sum;
}
}
built(1,1,sum);
for(int i=0;i<n;i++)
{
change(1,logo[i][0],logo[i][1],i+1);
}
memset(f,0,sizeof(f));
ans=0;
query(1);
cout<<ans<<endl;
}
return 0;
}