题意:给定n个区间[Li,Ri]以及n个整数vi. 现在要有一个集合,使得这个集合和任意[Li,Ri]都有 至少 vi个元素相同. 问这个集合最少要几个元素.
定义S(x) 表示[1,x]中选择的元素的个数. 那么就有S(Ri)−S(Li−1)>=vi
同时还有一个隐形的条件
0<=S(i+1)−S(i)<=1;
用链式前向星跑最长路即可
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define RI(n) scanf("%d",&(n)) #define RII(n,m) scanf("%d%d",&n,&m) #define RIII(n,m,k) scanf("%d%d%d",&n,&m,&k) #define RS(s) scanf("%s",s); #define ll long long #define pb push_back #define REP(i,N) for(int i=0;i<(N);i++) #define CLR(A,v) memset(A,v,sizeof A) #define inf 0x3f3f3f3f ////////////////////////////////////// const int N = 200000+6; int pos=0; struct node { int nex,to,v; }edge[N]; int head[N]; void add(int a,int b,int v) { edge[++pos].nex=head[a]; head[a]=pos; edge[pos].to=b; edge[pos].v=v; } int dis[N],vis[N]; int L,R; void spaf(int s) { rep(i,L,R) dis[i]=-inf; dis[s]=0; queue<int>q; q.push(s); vis[s]=1; while(!q.empty()) { int u=q.front();q.pop(); vis[u]=0; for(int i=head[u];i;i=edge[i].nex) { int v=edge[i].to; if(dis[v]<dis[u]+edge[i].v) { dis[v]=dis[u]+edge[i].v; if(!vis[v]) { vis[v]=1; q.push(v); } } } } } int main() { int n; while(~RI(n)) { pos=0; CLR(head,0); CLR(vis,0); L=inf; R=0; rep(i,1,n) { int a,b,c; RIII(a,b,c);a--; add(a,b,c); L=min(a,L); R=max(R,b); } rep(i,L,R-1) add(i,i+1,0),add(i+1,i,-1); spaf(L); cout<<dis[R]<<endl; } return 0; }
原文:https://www.cnblogs.com/bxd123/p/10770358.html