zoukankan      html  css  js  c++  java
  • poj 2528 数的离散化+线段树

    在一面墙上贴海报,贴的顺序给出了,求最后能被看到的海报数量。

    纯粹的线段树模拟题。

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

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

    比如题目给的样例:

    1 4
    2 6
    8 10
    3 4
    7 10
     
    用到的数有:1 2 3 4 6 7 8 10
    可以把它们映射为:
    1 2 3 4 6 7 8 10
    1 2 3 4 5 6 7 8

    这样建树的时候只开到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**
    ",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
    ",ans);
        }
    }
  • 相关阅读:
    C语言——总结回顾
    C语言——第十四、十五周作业
    题目思路——统计素数并求和
    题目思路——单词长度
    C语言——第七周作业
    C语言——第六周作业
    C语言——第四次作业
    C语言——第三次作业
    C语言——第二次作业
    C语言——第一次作业
  • 原文地址:https://www.cnblogs.com/lastone/p/5296064.html
Copyright © 2011-2022 走看看