您的位置:首页 > 其它

poj 2528 数的离散化+线段树

2016-03-19 19:31 330 查看
在一面墙上贴海报,贴的顺序给出了,求最后能被看到的海报数量。

纯粹的线段树模拟题。

但数据范围给了10^7,超内存了。

实际上这里用了一个小技巧,虽然墙的宽度是很大的,但海报数量只有10000,所以这10^7个数中真正用到的数很少,这样的话就只需要把没用到的数给“删去”,剩下来的数从小到大映射为新的数,这样空间复杂度就大大降低了。这就是数的离散化。

比如题目给的样例:

14
26
810
34
710


用到的数有:123467810

可以把它们映射为:

123467810
12345678
这样建树的时候只开到8就行了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
usingnamespacestd;
constintMAXN=20010;
intseg[MAXN*2];//线段树的结点编号从0开始。
intlnext[MAXN*2],rnext[MAXN*2];
intl[MAXN*2],r[MAXN*2];
inttot;
intbuildTree(intll,intrr)
{
intcur=tot++;
l[cur]=ll;
r[cur]=rr;
if(ll==rr)
{
seg[cur]=0;
//printf("%d**\n",seg[cur]);
lnext[cur]=rnext[cur]=-1;
returncur;
}
intmid=(ll+rr)>>1;
lnext[cur]=buildTree(ll,mid);
rnext[cur]=buildTree(mid+1,rr);
seg[cur]=0;
returncur;
}
booladd(intcur,intll,intrr,intval)
{
if(rnext[cur]!=-1&&lnext[cur]&&seg[rnext[cur]]&&seg[lnext[cur]]){
seg[cur]=1;
}
if(seg[cur])returnfalse;
if(ll>rr)swap(ll,rr);
if(l[cur]==ll&&r[cur]==rr)
{
seg[cur]=val;
returntrue;
}
bools1=0,s2=0;
intmid=(l[cur]+r[cur])>>1;
if(ll>=mid+1)
s1=add(rnext[cur],ll,rr,val);
elseif(rr<=mid)
s2=add(lnext[cur],ll,rr,val);
else
{
s1=add(lnext[cur],ll,mid,val);
s2=add(rnext[cur],mid+1,rr,val);
}
if(rnext[cur]!=-1&&lnext[cur]&&seg[rnext[cur]]&&seg[lnext[cur]]){
seg[cur]=1;
}
returns1||s2;
}

intdata[10005][2];
inty[20005],cur,ying[10000002];
intmain()
{
intT,n,ans;
scanf("%d",&T);
while(T--&&scanf("%d",&n)!=EOF)
{
ans=0;cur=1;tot=0;
for(inti=0;i<n;i++){
scanf("%d%d",&data[i][0],&data[i][1]);
y[cur++]=data[i][0];
y[cur++]=data[i][1];
}
y[0]=-1;
sort(y+1,y+cur);
intcc=1;
for(inti=1;i<cur;i++){
if(y[i]==y[i-1])continue;
ying[y[i]]=cc++;
}
buildTree(1,cc-1);
for(inti=n-1;i>=0;i--){
data[i][0]=ying[data[i][0]];
data[i][1]=ying[data[i][1]];
if(add(0,data[i][0],data[i][1],1))ans++;
}
printf("%d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: