首页 > 代码库 > hdu5124(树状数组+离散化)

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 1000000007using 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 1000000007using 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 1000000007using 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

 

hdu5124(树状数组+离散化)