Intervals

https://loj.ac/problem/10087

题目描述

  从[1,50000]中选出最少的整数,使得每个区间[ai,bi]中至少有ci个数被选出。

思路

  我们假设s[k]表示[1,k]中选出s[k]个数,那么对于给定区间[a,b]中选出c个数,实际就是s[b]-s[a-1]≥c。

  因此每一个约束条件可以转化为s[bi]≥s[ai-1]+ci,那么答案就是dis[maxnum],dis表示到这个最长路,不过为了保证图的连通性,我们还需要添加两个约束条件,即s[k+1]≥s[k],s[k+1]≤s[k]+1,。建完图后在图上跑一遍spfa即可。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=5e4+10;
const int INF=0x3f3f3f3f;
int nxt[N<<2],to[N<<2],head[N],w[N<<2],tot;
int dis[N],minn,maxx;
bool exist[N];
int read()
{
    int res=0,w=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){res=res*10+ch-'0';ch=getchar();}
    return res*w;
}
void clear()
{
    memset(head,0,sizeof(head));
    memset(exist,0,sizeof(exist));
    tot=0;minn=INF;maxx=-1;
}
void add_edge(int x,int y,int v)
{
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
    w[tot]=v;
}
void spfa(int s)
{
    for(int i=minn;i<=maxx;i++)
        dis[i]=-INF;
    queue<int>q;
    dis[s]=0;exist[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();q.pop();
        exist[u]=0;
//        cout<<u<<':'<<endl;
        for(int i=head[u];i;i=nxt[i])
        {
//            cout<<u<<' '<<to[i]<<endl;
            int v=to[i];
            if(dis[v]<dis[u]+w[i])
            {
                dis[v]=dis[u]+w[i];
                if(!exist[v])
                {
                    exist[v]=1;
                    q.push(v);
                }
            }
        }
    }
}
int main() 
{
    int n;
    clear();
    n=read();
    for(int i=1;i<=n;i++)
    {
        int l=read(),r=read(),x=read();
        add_edge(l-1,r,x);
        minn=min(minn,l-1);
        maxx=max(maxx,r);
    }
    for(int i=minn;i<=maxx;i++)
    {
        add_edge(i,i+1,0);
        add_edge(i+1,i,-1);
    }
    spfa(minn);
//    for(int i=minn;i<=maxx;i++)
//        printf("%d %d\n",i,dis[i]);
    printf("%d",dis[maxx]);
    return 0;
}

 

posted @ 2019-10-21 21:07  fbz  阅读(294)  评论(0编辑  收藏  举报