HDU 5124 lines

来源:互联网 发布:java反序列化漏洞原理 编辑:程序博客网 时间:2024/05/17 01:29
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

 
题目大意:给你数字n,接着输入n条线段(x轴上的);求整数点最大被覆盖的次数;

这道题可以贪心,也可以离散化+线段树,也可以离散化+树状数组;


贪心思路;
两个数组分别用来记录起点和终点,将他们排序;
用一个变量n记录,从前往后读,每读到一个起点n加一,每读到一个终点n-1;
输出过程中最大的n就好;
代码如下:

#include<stdio.h>
#include<algorithm>
using namespace std;
typedef long long LL;

int b[100005],e[100005];

void test()
{
    int n;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
        scanf("%d%d",&b[i],&e[i]);
    sort(b,b+n);
    sort(e,e+n);
    int x,y,m,mx;
    mx=m=x=y=0;
    while(x<n)
    {
        if(b[x]<=e[y]) m++, x++;
        else m--, y++;
        if( m > mx ) mx = m;
    }
    printf("%d\n",mx);
}
int main()
{
    int t;
    scanf("%d", &t);
    for(int i = 1; i <= t; i ++)
    {
        test();
    }
    return 0;
}

离散化+线段树思路:
这道题用过线段树的,一眼就看出可以线段树,但是数据范围太大,所以先离散化一下,就可以用线段树直接求解;

#include<stdio.h>
#include<algorithm>
using namespace std;

struct node
{
    int x,y;
};

struct SegmentTree//l,r分别存储的是当前树的区间,x储存的是当前树区间的最大值,ad基于lazy思想,储存是否向下更新;
{
    int l, r, x;
    int ad;
};

node s[100005];

SegmentTree tree[800005];
int a[200005];

void updata_up(int k)//向上更新
{
    tree[k].x = max(tree[k<<1].x, tree[k<<1|1].x);
}

void updata_down(int k)//向下更新;
{
    tree[k<<1].x += tree[k].ad;
    tree[k<<1].ad += tree[k].ad;
    tree[k<<1|1].x += tree[k].ad;
    tree[k<<1|1].ad += tree[k].ad;
    tree[k].ad = 0;
}

void build(int l,int r,int k)//建树;
{
    tree[k].l=l, tree[k].r=r, tree[k].ad=0;
    if(l==r)
    {
        tree[k].x=0;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,k<<1);
    build(mid+1,r,k<<1|1);
    updata_up(k);
}

void add(int l, int r, int k, int x)// 更新区间,将整个区间加一;
{
    if(tree[k].l>=l && tree[k].r<=r)
    {
        tree[k].x += 1;
        tree[k].ad += 1;
        return ;
    }
    if(tree[k].ad) updata_down(k);
    if(tree[k<<1].r>=l) add(l,r,k<<1,x);
    if(tree[k<<1|1].l<=r) add(l,r,k<<1|1,x);
    updata_up(k);
}

void test( )
{
    int n, t=0;
    scanf("%d",&n);
    for(int i=0; i<n; i++)
    {
        scanf("%d%d",&s[i].x, &s[i].y);
        a[t++] = s[i].x, a[t++] = s[i].y;
    }
    sort(a,a+t);
    for(int i=0; i<n; i++)
    {
        s[i].x = lower_bound(a, a+t, s[i].x) - a + 1;//离散化处理;
        s[i].y = lower_bound(a, a+t, s[i].y) - a + 1;
    }
    build(1, t, 1);
    for(int i=0; i<n; i++)
        add(s[i].x, s[i].y, 1, 1);
    printf("%d\n",tree[1].x);//直接输出树的最高层,即最大区间的最大值;
}

int main()
{
    int t;
    scanf("%d", &t);
    for(int i = 1; i <= t; i ++)
        test();
    return 0;
}




0 0