题意:有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; }