Intervals
题目描述
从[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; }