hdu5124(树状数组+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5124

题意:有n条线段,求被覆盖到次数最多的点的次数

分析:

1.可以转化成求前缀和最大的问题:将区间改成左闭右开(即右端点加1),排序,从左往右遍历,若为左端点则加一,右端点则减一。

2.树状数组,离散化一下,然后区间更新,单点查询。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define inf 1<<30
#define mod 1000000007
using namespace std;
int a[500010],n,m;
int c[200010];
struct node
{
    int l,r;
}s[100010];
int bin(int key,int n,int a[])
{
    int l=0,r=n-1;
    while(l<=r)
    {
        int m=(l+r)>>1;
        if(a[m]==key)return m;
        if(a[m]<key)l=m+1;
        else r=m-1;
    }
    return -1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int cnt=0,l,r;
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&l,&r);
            s[i].l=l;s[i].r=r;
            a[cnt++]=l;a[cnt++]=r;
        }
        sort(a,a+cnt);
        m=1;
        //离散化好模板
        for(int i=1;i<cnt;i++)
            if(a[i]!=a[i-1])a[m++]=a[i];
        for(int i=m-1;i>=0;i--)
            if(a[i]!=a[i-1]+1)a[m++]=a[i-1]+1;
        sort(a,a+m);
        for(int i=1;i<=n;i++)
        {
            l=bin(s[i].l,m,a);
            r=bin(s[i].r,m,a);
           c[l]++;c[r+1]--;
        }
        int ans=0,sum=0;
        for(int i=0;i<m;i++)
        {
            sum+=c[i];
            ans=max(ans,sum);
        }
        printf("%d\n",ans);
    }
}

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define inf 1<<30
#define mod 1000000007
using namespace std;
int a[500010],n,m;
int c[200010];
struct node
{
    int l,r;
}s[100010];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int d)
{
    while(x)
    {
        c[x]+=d;
        x-=lowbit(x);
    }
}
int sum(int x)
{
    int res=0;
    while(x<=m+1)
    {
        res+=c[x];
        x+=lowbit(x);
    }
    return res;
}
int bin(int key,int n,int a[])
{
    int l=0,r=n-1;
    while(l<=r)
    {
        int m=(l+r)>>1;
        if(a[m]==key)return m;
        if(a[m]<key)l=m+1;
        else r=m-1;
    }
    return -1;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d",&n);
        int cnt=0,l,r;
        memset(c,0,sizeof(c));
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&l,&r);
            s[i].l=l;s[i].r=r;
            a[cnt++]=l;a[cnt++]=r;
        }
        sort(a,a+cnt);
        m=1;
        //离散化好模板
        for(int i=1;i<cnt;i++)
            if(a[i]!=a[i-1])a[m++]=a[i];
        for(int i=m-1;i>=0;i--)
            if(a[i]!=a[i-1]+1)a[m++]=a[i-1]+1;
        sort(a,a+m);
        for(int i=1;i<=n;i++)
        {
            l=bin(s[i].l,m,a);
            r=bin(s[i].r,m,a);
            //树状数组习惯把区间右移了1,防止x+=lowbit(x)陷于死循环,不过这里加不是这个原因
            l+=2;r+=2;
            update(l-1,-1);update(r,1);
        }
        int ans=0;
        for(int i=2;i<=m+1;i++)ans=max(ans,sum(i));
        printf("%d\n",ans);
    }
}

当然不一定非得把坐标映射到x轴上,vextor<pair<int,int> >v;v[i].first用来把坐标排序,起到映射的作用。然后数组的下标就起到了压缩的作用。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdlib>
#include <vector>
#include <set>
#include <map>
#define LL long long
#define inf 1<<30
#define mod 1000000007
using namespace std;

vector <pair<int,int> > v;

int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
    {
        v.clear();
        int n;
        scanf("%d",&n);
        for (int i = 0; i < n; i++)
        {
            int x;
            scanf("%d",&x);
            v.push_back(make_pair(x,1));
            scanf("%d",&x);
            v.push_back(make_pair(x + 1,-1));
        }
        sort(v.begin(), v.end());
        int ans = 0;
        int sum = 0;
        for (int i = 0; i < v.size(); i++)
        {
            sum += v[i].second;
            ans = max(sum,ans);
        }
        printf("%d\n",ans);
    }
}

时间: 2024-12-28 16:42:35

hdu5124(树状数组+离散化)的相关文章

HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences                                  Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)                                             

BZOJ 1227 [SDOI2009] 虔诚的墓主人 离线+树状数组+离散化

鸣谢:140142耐心讲解缕清了我的思路 题意:由于调这道题调的头昏脑涨,所以题意自己搜吧,懒得说. 方法:离线+树状数组+离散化 解析:首先深表本蒟蒻对出题人的敬(bi)意(shi).这道题简直丧心病狂,看完题后大脑一片空白,整个人都不好了,刚开始的思路是什么呢?暴力思想枚举每个墓碑,然后计算每个墓碑的虔诚度,然后再来统计.不过看看数据范围呢?10^9*10^9的矩阵,最多才10^5个树,光枚举就已经超时了,所以肯定不行.(不过要是考试真没思路我就那么搞了- -!) 然后也想到来枚举墓碑,不过

求逆序数模板(树状数组+离散化 || 归并排序法)

一篇不错的讲解:http://www.cnblogs.com/shenshuyang/archive/2012/07/14/2591859.html 代码如下:(树状数组+离散化) #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int maxn=500017; int n; int aa[maxn

Ultra-QuickSort (树状数组离散化)

题目原意是用归并排序,刚学树状数组,就用了下 树状数组的离散化 离散化,是数据范围太大是所借用的利器,举个例子,有四个数99999999 1 123 1583 数据范围太大,而树状数组中的c数组开的范围是数据的范围,这时候就需要离散化,把四个数一次标号为1 2 3 4(即第一个数,第二个数...),按键值排序之后 依次为2 3 4 1(即从小到大排序为第二个数,第三个数...),所以,第二个数是最小的,即f[2]=1,f[3]=2,f[4]=3,f[1]=4,也就是把键值变为了1~n,相对大小还

hdu4325 树状数组+离散化

http://acm.hdu.edu.cn/showproblem.php?pid=4325 Problem Description As is known to all, the blooming time and duration varies between different kinds of flowers. Now there is a garden planted full of flowers. The gardener wants to know how many flower

高桥低桥(树状数组离散化)

1335: 高桥和低桥 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 362  Solved: 62 [Submit][Status][Web Board] Description 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算"淹了两次".举例说明: 假定高桥和低桥的高度分别是5和2,初始水位为1 第一次

Ultra-QuickSort(树状数组 + 离散化)

Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input seque

求逆序数数目(树状数组+离散化)

404在玩忍者印记(Mark of the Ninja)操纵忍者时遇到这样一个场景,两栋大楼之间有许多绳索,从侧面看,就像这个样子: 我们的忍者非常有好奇心,他可以观察到每个绳索的端点在两栋楼的高度,想知道这些绳索有多少个交点(图中黑色的点).他观察到不会建筑上不会有一点上有两个绳索,并且没有三条绳索共点. 输入描述 第一行:整数T,代表有T组数据. (1 <= T <= 100) 下一行:整数N,代表有N条绳索. (1 <= N <= 100000) 接下来Na行给出两个整数A_

POJ 2299 Ultra-QuickSort(树状数组+离散化)

题目大意: 就是说,给你一个序列,然后让你求出这个序列有多少个逆序对,所谓逆序对就是对于这个序列中的元素有a[i]>a[j] 且i<j存在. 其实原题是这样说的,给你一个序列,让你用最少的交换次数使得这个序列变成从小到大的排序. 解题思路: 一开始是想到了归并的思路,但是没有能写出来代码. 先来来范围吧,序列的长度n<=500000+4.   并且每个a[i]<=999 999 999,对于tree[i],我们知道这个数组肯定是放不下的,所以 我们要进行离散化的处理,关于离散化的处