您的位置:首页 > 其它

poj 2528 坐标离散化+线段树

2013-10-20 15:42 369 查看
题意大概就是给你一些墙纸的宽度,也就是覆盖区间,比如1 4,就是说贴满了1到4这个瓷砖,这个题由于数据太大了10的9次方,如果这样建树的话明显不是TLE就是MLE

那么,就用到了坐标离散化,听起来很高端的样子,其实就是一个一一映射的关系。。

比入1000 400 10000000这三个数字那么我们就把它们排序,然后分别映射为2 1 3,这样线段树的区间就只需要1~3,而不是1~10000000,节约的太多的内存和时间

然后剩下的就是涂色问题了,,这个没什么好讲的~~

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
int cnt[20006<<2];   //这里注意如果是10000*4的话是不行的,必须要比它大,我开了个20000。。。就是这里WA无数次的掩面路过
int hash[10000005];
int x[30005],ans;
bool vis[30005];
struct node
{
int x,y;
}a[20005];
void init(int l,int r,int index)
{
cnt[index]=-1;
if(l==r)
return ;
int m=(l+r)>>1;
init(lc);
init(rc);
}
void build(int l,int r,int index,int L,int R,int num)
{
int m=(l+r)>>1;
if(L==l && R==r)
{
cnt[index]=num;
return;
}
else
{
if(cnt[index]>=0)
{
cnt[index<<1]=cnt[index];
cnt[index<<1|1]=cnt[index];
cnt[index]=-1;
}
if(R<=m)
build(lc,L,R,num);
else if(L>m)
build(rc,L,R,num);
else
{
build(lc,L,m,num);
build(rc,m+1,R,num);
}
}
}
void query(int l,int r,int index)
{
if(cnt[index]!=-1)
{
vis[cnt[index]]=1;
}
int m=(l+r)>>1;
if(l==r)
return ;
if(cnt[index]>=0)
{
cnt[index<<1]=cnt[index];
cnt[index<<1|1]=cnt[index];
cnt[index]=-1;
}
query(lc);
query(rc);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ans=0;
memset(hash,-1,sizeof(hash));
int n,len=0;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
x[len++]=a[i].x;
x[len++]=a[i].y;
}
sort(x,x+len);
int k=0;
for(int i=0;i<len;i++)
{
if(hash[x[i]]==-1)
{
hash[x[i]]=k++;
}
}
init(0,k-1,1);
for(int i=0;i<n;i++)
build(0,k-1,1,hash[a[i].x],hash[a[i].y],i);
memset(vis,false,sizeof(vis));
query(0,k-1,1);
for(int i=0;i<k;i++)
{
if(vis[i])
ans++;
}
printf("%d\n",ans);

}
// system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: