由于颜色只有七种,线段有100000条,所以可以用DP[i][j]表示最后一个线段的右端点位置 < i,且包含 j 颜色的最大长度,(状态压缩,用七位二进制数表示七种颜色的状态)。
l,r范围较大,但n较小,所以将其进行离散化处理。
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 1e5 + 10;
int n, m, Rank[N*2], Rn;
int head[N<<1], nt[N<<1], _id[N<<1], sz;
struct node{
int l, r, c, len;
friend bool operator < (node a, node b) {
return a.r < b.r;
}
}a[N];
LL dp[N*2][(1<<7)+10];
int get_Rank(int x) {
return lower_bound(Rank+1, Rank+1+Rn, x) - Rank;
}
int count(int x) {
int ans = 0;
while(x) {
ans += x & 1;
x >>= 1;
}
return ans;
}
int main()
{
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);
a[i].len = a[i].r - a[i].l; a[i].c --;
Rank[++Rn] = a[i].l; Rank[++Rn] = a[i].r;
}
sort(Rank+1, Rank+1+Rn);
Rn = unique(Rank+1, Rank+1+Rn) - Rank - 1;
sort(a+1, a+1+n);
for(int i=1;i<=n;i++) {
int rk = get_Rank(a[i].r);
nt[++sz] = head[rk], _id[sz] = i, head[rk] = sz;
}
for(int i=1;i<=Rn;i++) {
for(int j=0;j<1<<7;j++) {
dp[i][j] = max(dp[i][j], dp[i-1][j]);
for(int k=head[i]; k; k=nt[k]) {
int to = _id[k];
int col = (1<<a[to].c) | j;
int pre = get_Rank(a[to].l)-1;
if(dp[pre][j] == 0 && j) continue;
dp[i][col] = max(dp[i][col], dp[pre][j] + a[to].len);
}
}
}
LL ans = 0;
for(int i=1;i<1<<7;i++) {
if(count(i) == m) ans = max(ans, dp[Rn][i]);
}
if(ans == 0) ans = -1;
printf("%lld\n", ans);
return 0;
}