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);

    }

}
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\n",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\n",ans);

    }

}
View Code

 

你可能感兴趣的:(树状数组)