poj 2528 数的离散化+线段树

来源:互联网 发布:js鼠标点击拖动事件 编辑:程序博客网 时间:2024/04/29 16:36
在一面墙上贴海报,贴的顺序给出了,求最后能被看到的海报数量。

纯粹的线段树模拟题。

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

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

比如题目给的样例:

1 42 68 103 47 10
 
用到的数有:1 2 3 4 6 7 8 10
可以把它们映射为:
12346781012345678

 

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

 

#include<iostream>#include<algorithm>#include<cstring>#include<cstdio>using namespace std;const int MAXN=20010;int seg[MAXN*2];//线段树的结点编号从0开始。int lnext[MAXN*2],rnext[MAXN*2];int l[MAXN*2],r[MAXN*2];int tot;int buildTree(int ll,int rr){    int cur=tot++;    l[cur]=ll;    r[cur]=rr;    if(ll==rr)    {        seg[cur] = 0;        //printf("%d**\n",seg[cur]);        lnext[cur]=rnext[cur]=-1;        return cur;    }    int mid=(ll+rr)>>1;    lnext[cur]=buildTree(ll,mid);    rnext[cur]=buildTree(mid+1,rr);    seg[cur]=0;    return cur;}bool add(int cur,int ll,int rr,int val){    if(rnext[cur]!=-1&&lnext[cur]&&seg[rnext[cur]]&&seg[lnext[cur]])  {        seg[cur]=1;    }    if(seg[cur]) return false;    if(ll>rr) swap(ll,rr);    if(l[cur]==ll&&r[cur]==rr)    {        seg[cur]=val;        return true;    }    bool s1=0,s2=0;    int mid = (l[cur]+r[cur])>>1;    if(ll>=mid+1)        s1 = add(rnext[cur],ll,rr,val);    else if(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;    }    return s1||s2;}int data[10005][2];int y[20005],cur,ying[10000002];int main(){    int T,n,ans;    scanf("%d",&T);    while(T--&&scanf("%d",&n)!=EOF)    {        ans=0;cur=1;tot=0;        for(int i=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);        int cc=1;        for(int i=1;i<cur;i++) {            if(y[i]==y[i-1]) continue;            ying[y[i]]=cc++;        }        buildTree(1,cc-1);        for(int i=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);    }}
0 0
原创粉丝点击