您的位置:首页 > 其它

POJ 2528 Mayor's posters (离散化和线段树使用)

2012-02-04 14:36 417 查看
还是做了线段树的题目,玩了两天也要继续看看题目了。之前就有看离散化的概念,大家可以去百度百科一下,简单转载一个例子

离散化 的大概思路 : 比如说给你一组 数据 1 4 1000 100000, 如果直接
开线段, 显然是浪费, 那么我们只要 进行 映射 :
1 1
4 2
1000 3
100000 4
接下来 我们只要对 1 2 3 4 建立线段树就行了 只需要[1,4]的区间。

差不多就是这样了,这样就可以大大减少使用的内存空间。

这道题目的数据范围非常大1 <= li <= ri <= 10000000;直接开肯定爆掉的,而且光建树就浪费非常多的时间了,所以做离散化映射。因为1 <= n <= 10000,所以建树开四倍大空间就行,又以为一个输入数据两个点,所以是八倍空间。本题重点是离散化的使用,记得之前比赛题目就是这题,那时候还不会线段树,就无限尝试一直WA,现在终于解决了。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include<algorithm>
using namespace std;
struct NODE
{
int l,r,val;
}tree[80005];
struct node
{
int l,r;
}num[10001];
bool vis[10001];
int ans,lag[20001],n;
void build(int l,int r,int index) //建树
{
tree[index].l=l;
tree[index].r=r;
tree[index].val=0;
if(l==r)
return;
int mid=(l+r)/2;
build(l,mid,2*index);
build(mid+1,r,2*index+1);
}
int find(int x) //二分查找对应点
{
int l=0,r=n-1;
while(l<=r)
{
int mid=(l+r)/2;
if(lag[mid]==x)
return mid+1;
else
if(lag[mid]>x)
r=mid-1;
else
l=mid+1;
}
}
void update(int l,int r,int index,int c) //更新线段树,标记属于哪个宣传
{
if(l==tree[index].l && r==tree[index].r)
{
tree[index].val=c;
return;
}
if(tree[index].val>-1)
{
tree[2*index].val=tree[2*index+1].val=tree[index].val;
tree[index].val=-1;
}
int mid=(tree[index].l+tree[index].r)/2;
if(mid>=l && mid+1<=r)
{
update(l,mid,2*index,c);
update(mid+1,r,2*index+1,c);
}
else
if(r<=mid)
update(l,r,2*index,c);
else
if(l>=mid+1)
update(l,r,2*index+1,c);
}
void query(int l,int r,int index)
{
if(tree[index].val>-1) //询问的核心 满足条件的情况
{
int tc=tree[index].val;
if(!vis[tc] && tc)
{
vis[tc]=1;
ans++;
}
return;
}
int mid=(tree[index].l+tree[index].r)/2;
if(l<=mid && r>=mid+1)
{
query(l,mid,2*index);
query(mid+1,r,2*index+1);
}
else
if(r<=mid)
query(l,r,2*index);
else
if(l>=mid+1)
query(l,r,2*index+1);
}
int main()
{
int i,t,N,pre,l,r;
scanf("%d",&t);
while(t--)
{
memset(vis,0,sizeof(vis));
scanf("%d",&N);
for(i=0;i<N;i++) //输入数据做映射
{
scanf("%d%d",&num[i].l,&num[i].r);
lag[2*i]=num[i].l;
lag[2*i+1]=num[i].r;
}
sort(lag,lag+2*N);
n=pre=0;
for(i=0;i<2*N;i++) //去除相同数据
{
if(lag[i]!=pre)
{
pre=lag[i];
lag[n++]=lag[i];
}
}
build(1,n,1);
for(i=0;i<N;i++) //开始一个个点的更新
{
l=find(num[i].l);
r=find(num[i].r);
update(l,r,1,i+1);
}
ans=0;
query(1,n,1);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: