hihoCoder:#1079(线段树+离散化)

题目大意:给n个区间,有的区间可能覆盖掉其他区间,问没有完全被其他区间覆盖的区间有几个?区间依次给出,如果有两个区间完全一样,则视为后面的覆盖前面的。

题目分析:区间可能很长,所以要将其离散化。但离散化之后区间就变成了连续的,不再是离散的。也就是叶子由左右端点为u、u变成了左右端点为u-1、u,左右儿子有(l,mid)和(mid+1,r)变成了(l,mid)和(mid,r)。所以离散化之后要以长度为1的区间为叶子节点建立线段树,而不是以1、2、3...为叶子节点建线段树。

代码如下:

# include<iostream>
# include<cstdio>
# include<set>
# include<map>
# include<cstring>
# include<algorithm>
using namespace std;

const int N=200000;

int tr[N*4+5];
int n,m;
int lazy[N*4+5];
int x[N+5],y[N+5];
set<int>s;
map<int,int>mp;
int num[N+5];

void pushDown(int rt,int l,int r)
{
    if(lazy[rt]==-1) return ;
    lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
    tr[rt<<1]=tr[rt<<1|1]=tr[rt];
    lazy[rt]=-1;
}

void update(int rt,int l,int r,int L,int R,int val)
{
    if(L<=l&&r<=R){
        tr[rt]=val;
        lazy[rt]=val;
    }else{
        pushDown(rt,l,r);
        int mid=l+(r-l)/2;
        if(L<=mid) update(rt<<1,l,mid,L,R,val);
        if(R>mid) update(rt<<1|1,mid+1,r,L,R,val);
    }
}

void query(int rt,int l,int r)
{
    if(l==r){
        if(tr[rt]!=-1) s.insert(tr[rt]);
        return ;
    }
    if(lazy[rt]!=-1){
        s.insert(tr[rt]);
        return ;
    }
    int mid=l+(r-l)/2;
    query(rt<<1,l,mid);
    query(rt<<1|1,mid+1,r);
}

int f(int l,int r,int x)
{
    while(l<r){
        int mid=l+(r-l)/2;
        if(num[mid]<x)
            l=mid+1;
        else
            r=mid;
    }
    return l;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        num[0]=0;
        mp.clear();
        for(int i=0;i<n;++i){
            scanf("%d%d",x+i,y+i);
            if(mp[x[i]]==0) num[++num[0]]=x[i],++mp[x[i]];
            if(mp[y[i]]==0) num[++num[0]]=y[i],++mp[y[i]];
        }
        sort(num+1,num+num[0]+1);
        memset(tr,-1,sizeof(tr));
        memset(lazy,-1,sizeof(lazy));
        for(int i=0;i<n;++i){
            int a=f(1,num[0]+1,x[i]);
            int b=f(1,num[0]+1,y[i]);
            update(1,1,num[0]-1,a,b-1,i);
        }
        s.clear();
        query(1,1,num[0]-1);
        printf("%d\n",s.size());
    }
    return 0;
}

  

时间: 2024-08-02 07:47:34

hihoCoder:#1079(线段树+离散化)的相关文章

hihoCoder#1079(线段树+坐标离散化)

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho在回国之后,重新过起了朝7晚5的学生生活,当然了,他们还是在一直学习着各种算法~ 这天小Hi和小Ho所在的学校举办社团文化节,各大社团都在宣传栏上贴起了海报,但是贴来贴去,有些海报就会被其他社团的海报所遮挡住.看到这个场景,小Hi便产生了这样的一个疑问——最后到底能有几张海报还能被看见呢? 于是小Ho肩负起了解决这个问题的责任:因为宣传栏和海报的高度都是一样的,所以宣传栏可以被视作长度为L的一段区间,且有

POJ_2528 Mayor&#39;s poster(线段树+离散化)

题目请点我 题解: 这道题与之前的题目相比重点在于一个映射的预处理,题目所给的区间达到10000000,而最多只有10000个点,如果直接建树的话太过于空旷.把这些区间的左右节点一一对应,最多有4×10000个点,远小于之前的10000000,而且区间之间的对应关系也不会改变. 举个例子: 区间:[2,6],[4,8],[6,10] 我们进行下面对应: 2 4 6 8 10 1 2 3 4 5 则原区间变为[1,3],[2,4],[3,5].可以发现它们之间的覆盖关系并没有改变,但是却紧凑了很多

POJ - 2528 - Mayor&#39;s posters 【线段树+离散化+补点】

http://poj.org/problem?id=2528 #include <cstdio> #include <iostream> #include <set> #include <cstring> #include <string> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 32768 + 5; in

HDU5124:lines(线段树+离散化)或(离散化思想)

http://acm.hdu.edu.cn/showproblem.php?pid=5124 Problem Description John has several lines. The lines are covered on the X axis. Let A is a point which is covered by the most lines. John wants to know how many lines cover A. Input The first line conta

hdu1828 Picture(线段树+离散化+扫描线)两种方法

C - Picture Time Limit:2000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I64u Submit Status Description A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

hdu 5124 lines (线段树+离散化)

lines Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 620    Accepted Submission(s): 288 Problem Description John has several lines. The lines are covered on the X axis. Let A is a point which

poj2528 线段树+离散化

1 //Accepted 1960K 110MS 2 //线段树+离散化 3 //把所有的坐标排序,从小到大编号,建立线段树 4 #include <cstdio> 5 #include <cstring> 6 #include <iostream> 7 #include <queue> 8 #include <cmath> 9 #include <algorithm> 10 using namespace std; 11 /** 1

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

poj2528--Mayor&#39;s posters(线段树+离散化)

Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 41785   Accepted: 12164 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral post