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 is covered by the most lines. John wants to know how many lines cover A.

Input

The first line contains a single integer T(1≤T≤100)(the
data for N>100 less
than 11 cases),indicating the number of test cases.

Each test case begins with an integer N(1≤N≤105),indicating
the number of lines.

Next N lines contains two integers Xi and Yi(1≤Xi≤Yi≤109),describing
a line.

Output

For each case, output an integer means how many lines cover A.

Sample Input

2
5
1 2
2 2
2 4
3 4
5 1000
5
1 1
2 2
3 3
4 4
5 5

Sample Output

3
1

题意就是求区间的最大值的,可以用线段树+离散化处理,使得坐标区间变小。

如[2,5],[3, 100]离散化后,先排序{2,3,5,100},对应下标值可以变为{1,2,3,4} ,对应时可以去重(见代码)。

区间变为[1,3],[2,4],区间的大小关系不变。

#include<stdio.h>
#include<math.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
using namespace std;
#define N 200005
#define ll __int64
struct node
{
    int l,r;
    int v,f;   //v记录最大值,f记录当前层累积的值
}f[N*3];
struct st     //记录原始区间的左右端点
{
    int x,id;
}a[N];
int pos[N/2][2];  //记录区间端点
bool cmp(st a,st b)
{
    return a.x<b.x;
}

void creat(int t,int l,int r)
{
    f[t].l=l;
    f[t].r=r;
    f[t].v=f[t].f=0;
    if(l==r)
        return ;
    int tmp=t<<1,mid=(l+r)>>1;
    creat(tmp,l,mid);
    creat(tmp|1,mid+1,r);
}

void update(int t,int l,int r)
{
    int tmp=t<<1,mid=(f[t].l+f[t].r)>>1;
    if(f[t].l==l&&f[t].r==r)
    {
        f[t].v++;
        f[t].f++;
        return ;
    }
    if(f[t].f)      //下压操作push_down,每次加上累计值
    {
        f[tmp].v+=f[t].f;
        f[tmp|1].v+=f[t].f;
        f[tmp].f+=f[t].f;
        f[tmp|1].f+=f[t].f;
        f[t].f=0;          //标记值f置为零
    }
    if(r<=mid)
        update(tmp,l,r);
    else if(l>mid)
        update(tmp|1,l,r);
    else
    {
        update(tmp,l,mid);
        update(tmp|1,mid+1,r);
    }
    f[t].v=max(f[tmp].v,f[tmp|1].v);  //上压操作push_up
}
int main()
{
    int T,i,n;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&pos[i][0],&pos[i][1]);
            a[i*2].x=pos[i][0];
            a[i*2].id=-(i+1);        //记录下标,负值为起点,正值为终点
            a[i*2+1].x=pos[i][1];
            a[i*2+1].id=i+1;
        }
        sort(a,a+n*2,cmp);
        int t=1,x=a[0].x;    //t为重新赋给区间的坐标值
        for(i=0;i<n*2;i++)
        {
            if(x!=a[i].x)  //可以达到去除重复值的效果
            {
                t++;
                x=a[i].x;
            }
            if(a[i].id<0)
                pos[-1*a[i].id-1][0]=t;
            else
                pos[a[i].id-1][1]=t;
        }
        creat(1,1,n*2);
        for(i=0;i<n;i++)
        {
            update(1,pos[i][0],pos[i][1]);
        }
        printf("%d\n",f[1].v);
    }
    return 0;
}
时间: 2024-10-07 06:47:10

hdu 5124 lines (线段树+离散化)的相关文章

HDU 1542 Atlantis 线段树+离散化+扫描线

题意:给出一些矩形的最上角坐标和右下角坐标,求这些矩形的面积并. NotOnlySuccess 线段树专辑中扫描线模板题,弱智的我对着大大的代码看了一下午才搞懂. 具体见思路见注释=.= #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid

POJ 1177/HDU 1828 picture 线段树+离散化+扫描线 轮廓周长计算

求n个图矩形放下来,有的重合有些重合一部分有些没重合,求最后总的不规则图型的轮廓长度. 我的做法是对x进行一遍扫描线,再对y做一遍同样的扫描线,相加即可.因为最后的轮廓必定是由不重合的线段长度组成的,这样理论上是对的 要注意处理高度相同的线段,把底边优先处理(在代码里就是f标记为1的线段),因为若是一个矩形的底边和另一个矩形的上边重合,则这个轮廓肯定不能算 不过POJ和HDU的数据好像都比较弱,我没进行上面的细节处理也AC了,不过一个很简单的数据就会不对,所以还是要处理一下才是真正正确的代码 我

HDU 1542 Atlantics 线段树+离散化扫描

将 x 轴上的点进行离散化,扫描线沿着 y 轴向上扫描 每次添加一条边不断找到当前状态有效边的长度 , 根据这个长度和下一条边形成的高度差得到一块合法的矩形的面积 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 6 using namespace std; 7 8 const int MAX=200+10; 9 int flag[MAX&l

HDU 4325-Flowers(线段树+离散化)

题意: 给出每个花开花的时间段,每询问一个时间点输出该时间点开花的数量 分析: 线段树的区间更新,单点查询,但发现时间很大,没法存区间,就想到了离散化. 离散化就是把要处理的数据统一起来重新标号. #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio>

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

HDU 3743 Frosh Week (线段树+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3743 Frosh Week Time Limit : 2000/1000ms (Java/Other)   Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 5   Accepted Submission(s) : 1 Font: Times New Roman | Verdana | Georgia Font Size: 

HDU 3642 线段树+离散化+扫描线

题意:给你N个长方体的左下角和右上角坐标,问你空间中有多少体积是被大于两个不同的立方体覆盖的.x,y~10^6 z~500 考虑到给的z比较小,所以可以直接枚举z,然后跑二维的扫描线就好. 关于处理被不同的线段覆盖三次的问题,可以维护四个信息,cnt,once,twice,more,然后相互推出结果就好. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #

HDU 1255 覆盖的面积 (扫描线 线段树 离散化)

题目链接 题意:中文题意. 分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt>=0改成cnt>=2就行了,. 但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了,因为虽然现在都不等于 2,但是之前的那个线段加上现在的已经覆盖2次了. 1 #include <iostream> 2 #include <cstdio> 3 #include <vector> 4 #include <cstring> 5 #include &

HDU 1542 Atlantis(线段树扫描线)

http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6788    Accepted Submission(s): 2970 Problem Description There are several ancient Greek