【算法】贪心

1>不相交区间区间问题

活动安排

求不相交区间个数

这里选择将r作为限制,以达到全局最优的目的

策略:选择对后面影响小的

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int n;
const int N=1003;
struct node
{
    int l,r;
    bool operator < (const node & o)
    { return r==o.r?l<o.l:r<o.r; }
}d[N];
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&d[i].l ,&d[i].r );
    sort(d+1,d+n+1);
    
    int cnt=1,nw=d[1].r ;
    for(int i=2;i<=n;i++)
        if(d[i].l >=nw) cnt++,nw=d[i].r ;
    
    printf("%d\n",cnt);
    return 0;
}

2>区间选点问题

尽量让每个点给多个区间使用,即尽量在重叠区域种树

因为点的分布可能是:

l 0 0 0 1 1 0 1 1 0 r

所以只能把每个点的数记在每个点上,然后每个点只能种一次,所以用us记录

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
int m,n;
const int N=5003;
struct node
{
    int l,r,nd;
    bool operator < (const node & o)
    { return r==o.r?l<o.l:r<o.r; }
}d[N];
int tr[30003];
bool us[30003];
int lowbit(int x)
{ return x&(-x); }
void add(int x)
{
    for(;x<=m;x+=lowbit(x))
        tr[x]++;
}
int find(int l,int r)
{
    int ans=0;
    for(;r;r-=lowbit(r))
        ans+=tr[r];
    for(;l;l-=lowbit(l))
        ans-=tr[l];
    return ans;
}

int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=n;i++) scanf("%d%d%d",&d[i].l ,&d[i].r ,&d[i].nd );
    sort(d+1,d+n+1);
    
    int cnt=0;
    for(int i=1;i<=n;i++)
    {
        int t=d[i].nd - find(d[i].l -1,d[i].r );
        if(t>0)
        {
            cnt+=t;
            while(t--) 
            {
                while(us[d[i].r ]) d[i].r --;
                add(d[i].r ),us[d[i].r ]=true;
            }
        }
    }
    
    printf("%d\n",cnt);
    return 0;
}

未完待续

猜你喜欢

转载自www.cnblogs.com/xwww666666/p/11480896.html