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
",ans);
    }
}
View Code


 

#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
",ans);
    }
}
View Code

 当然不一定非得把坐标映射到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
",ans);
    }
}
View Code
原文地址:https://www.cnblogs.com/lienus/p/4132396.html