列表

详情


NC50387. Intervals

描述

给定n个闭区间和n个整数c_i。你需要构造一个整数集合Z,使得对于任意,Z中满足的整数x不少于c_i个,求这样的整数集合Z最少包含多少个数。
简而言之就是,从中选出尽量少的整数,使每个区间内都有至少c_i个数被选出。

输入描述

第一行一个整数n,表示区间个数;
以下n行每行描述这些区间,第i+1行三个整数a_i,b_i,c_i,由空格隔开。

输出描述

一行,输出满足要求的序列最少整数个数。

示例1

输入:

5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

输出:

6

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 93ms, 内存消耗: 4460K, 提交时间: 2020-01-02 16:18:35

#include<bits/stdc++.h>
using namespace std;

const int MAXN = 5e4+2;
// b - a >= c => a <= b - c
// a <= (a + 1) 
// (a+1) <= a + 1;

// 最长路求最小值 
// b - a >= c
// (a+1) - a >= 0
// a - (a+1) >= -1
// add_edge(a, b, c);
typedef pair<int, int> pii;
int N;
vector<pii> G[MAXN];
int dis[MAXN];
bool inq[MAXN];
int inqCnt[MAXN];
int spfa() {
  memset(dis, 0x8f, sizeof(dis));
  // for (int i = 0; i <= N; i++) dis[i] = -0x3f3f3f3f;
  queue<int> Q;
  dis[0] = 0;
  Q.push(0);
  inq[0] = true;
  inqCnt[0]++;
  while (!Q.empty()) {
    int s = Q.front(); Q.pop();
    inq[s] = false;
    // cout << "Pop: " << s << " " << dis[s] << endl;
    for (auto it: G[s]) {
      int t = it.first, w = it.second;
      if (dis[t] < dis[s] + w) {
        dis[t] = dis[s] + w;
        if (inq[t]) continue;
        if (++inqCnt[t] >= N) return -1;
        inq[t] = true;
        Q.push(t);
        // cout << "Push " << t << " " << dis[t] << endl; } 
      }
    }
  }
  return dis[N];
}
int main() {
  int n; cin >> n;
  while (n--) {
    int a, b, c; cin >> a >> b >> c;
    b++;
    G[a].push_back({b, c});
    N = max(N, b);
  }
  for (int i = 0; i < N; i++) G[i].push_back({i+1, 0});
  for (int i = 0; i < N; i++) G[i+1].push_back({i, -1});
  cout << spfa() << endl;
}

C++(clang++11) 解法, 执行用时: 35ms, 内存消耗: 4216K, 提交时间: 2020-12-02 08:45:21

#include<bits/stdc++.h>
#define epb emplace_back
#define ep emplace
#define mp make_pair
#define pii pair<int,int>
#define v second
#define w first
using namespace std;
const int nn=51201;
bool in[nn];
int n,mab,a,b,c,u,dist[nn];
vector<pii>to[nn];
queue<int>q;
int main(){
	memset(dist,128,sizeof dist),
	dist[0]=0,scanf("%d",&n);
	for(int i=0;i<n;i++)
		scanf("%d%d%d",&a,&b,&c),
		mab=max(mab,++b),
		to[a].epb(mp(c,b));
	for(int i=0;i<mab;i++)
		to[i].epb(mp(0,i+1)),
		to[i+1].epb(mp(-1,i));
	for(q.ep(0);!q.empty();q.pop()){
		u=q.front(),in[u]=false;
		for(pii i:to[u])
			if(dist[u]+i.w>dist[i.v]){
				dist[i.v]=dist[u]+i.w;
				if(!in[i.v])q.ep(i.v);
			}
	}printf("%d\n",dist[mab]);
	return 0;
}

上一题