题意:有N条线段,每天线段有左右端点l、r,并且线段的长度是r-l+1,且线段有价值c,现在我们想要找两条线段,使得两条线段的长度和为X,并且两线段不相交。如果没有这样的答案输出-1,否则输出最小价值。
那么,很简单的,我们可以对l进行生序排序,于是直接查r在“l”之前的线段,我们用map去记录一下对应的长度,然后就可以了。
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
#define pii pair<int, int>
#define MP(a, b) make_pair(a, b)
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 2e5 + 7;
int N, M;
struct Line
{
int l, r, c;
inline void In() { scanf("%d%d%d", &l, &r, &c); }
friend bool operator < (Line e1, Line e2) { return e1.l < e2.l; }
} a[maxN];
vector<Line> vt[maxN];
map<int, int> mp;
int main()
{
scanf("%d%d", &N, &M);
for(int i = 1; i <= N; i ++) a[i].In();
sort(a + 1, a + N + 1);
int ans = -1;
for(int i = 1, pos = 1, len, cost; i <= N; i ++)
{
while(pos <= a[i].l)
{
for(Line it : vt[pos])
{
len = it.r - it.l + 1;
cost = it.c;
if(!mp[len]) mp[len] = cost;
else mp[len] = min(mp[len], cost);
}
pos ++;
}
len = a[i].r - a[i].l + 1;
if(mp[M - len])
{
if(~ans) ans = min(ans, a[i].c + mp[M - len]);
else ans = a[i].c + mp[M - len];
}
vt[a[i].r + 1].push_back(a[i]);
}
printf("%d\n", ans);
return 0;
}

京公网安备 11010502036488号