链接:https://www.nowcoder.com/acm/contest/212/C
来源:牛客网
七彩线段
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述
听说彩虹有七种颜色?
一维坐标轴上n条线段,每条线段左端点l,右端点r,颜色为c,从中选m种颜色的互不接触的线段,每种颜色可选多条,所选线段的总长度最长为多少?
输入描述:
第一行2个整数 n, m; 接下来n行,每行3个整数l, r, c。
输出描述:
一个整数,表示所选线段的最长的总长度;若选不了,输出-1;
示例1
输入
4 2 1 3 1 4 5 1 5 8 2 7 9 3
输出
5
示例2
输入
4 3 1 3 1 4 5 1 5 8 2 7 9 3
输出
-1
备注:
1 <= n <= 100000; 1 <= m <= 7; 1 <= l < r <= 1000000000; 1 <= c <= 7;
#include <bits/stdc++.h>
using namespace std;
const int mn = 100000;
struct node
{
int l, r, c;
} a[mn];
bool cmp(const node& a, const node& b)
{
return a.r < b.r;
} /// 按右边界排序
int dp[mn][150];
int main()
{
int n, m;
scanf("%d %d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%d %d %d", &a[i].l, &a[i].r, &a[i].c);
sort(a + 1, a + n + 1, cmp);
memset(dp, -1, sizeof dp);
a[0].l = a[0].r = a[0].c = 0;
dp[0][0] = 0;
for (int i = 1; i <= n; i++)
{
int t = 0;
int l = 0, r = i - 1;
while (l <= r)
{
int mid = (l + r) / 2;
if (a[mid].r < a[i].l)
{
l = mid + 1;
t = mid;
}
else
r = mid - 1;
} /// 二分查找不接触的前一条线段
for (int j = 0; j < (1 << 7); j++) /// 二进制枚举前i条线段选择的颜色情况
{
if (dp[i - 1][j] != -1)
dp[i][j] = dp[i - 1][j]; // 不选择当前线段
if ((j >> (a[i].c - 1)) & 1) // 该色在枚举颜色范围内 可选
{
if (dp[t][j - (1 << (a[i].c - 1))] != -1) // 前 t 条无当前色
dp[i][j] = max(dp[i][j], dp[t][j - (1 << (a[i].c - 1))] + a[i].r - a[i].l);
if (dp[t][j] != -1) // 前 t 条已经有当前色
dp[i][j] = max(dp[i][j], dp[t][j] + a[i].r - a[i].l);
}
}
}
int ans = 0;
for (int i = 0; i < (1 << 7); i++) // 枚举所有组合出的颜色情况
{
int t = 0;
for (int j = 0; j < 7; j++)
if (i >> j & 1)
t++;
if (t == m) //选择了 m 种颜色
ans = max(ans, dp[n][i]);
}
if (ans == 0)
cout << "-1" << endl;
else
cout << ans << endl;
}