Problem Link:CF 1313D
Solution:
无语辽,看了一遍题想了半天都不会,看着 k ≤ 8 k \leq 8 k≤8总感觉是要状压,想了半天也压不了啊,一个点可能有非常多线段覆盖,所以一直想能不能贪心。后面看了官方题解发现不太对劲,回头仔细看了看题发现是数据保证每个点最多有 k k k条线段覆盖,而不是让你选每个点最多只能选 k k k条线段。。。
害,知道了正确题意题解也相当明显了, k ≤ 8 k \leq 8 k≤8明显就是要让你暴力记录的,所以就直接 d p dp dp暴力选择线段就好了。
大致的方向确定了,思考具体要怎么写。首先肯定是离散化坐标,统计答案的时候展开加上。
考虑如何维护当前的线段。开一个数组用来记录每个左端点在二进制中的位置,这是为了右端点的时候删去相应的位置。那么如何知道当前的左端点应该放在哪里?其实也简单,放在当前最低位的 0 0 0就行了,这个可以用一个整数维护,也可以用一个 s e t set set维护。
另外还有个细节,读入线段的时候把右端点加一,这样做是为了排序的时候对于相同位置的情况,左端点应该先处理。举个例子就一个点的情况,虽然左右端点相同,但显然应该先处理左端点。这样子计算答案的方式也要换一下,直接当前端点 − - −上一个端点就行了。
这题真是挺难搞的,对我来说,搞了好久好久。虽然最后写出来的代码比较简单,但是8太好理解,尤其自己想完全不知道该怎么设计这个很明显的 D P DP DP。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define endl "\n"
#define fi first
#define se second
#define db double
#define gcd __gcd
#define pb push_back
#define mp make_pair
#define lowbit(x) (x & (-x))
#define PII pair
#define all(x) x.begin(), x.end()
#define debug(x) cout << #x << " = " << x << endl
#define rep(i, a, b) for(__typeof(b) i = a; i <= (b); i++)
#define Rep(i, a, b) for(__typeof(a) i = a; i >= (b); i--)
#define FAST ios::sync_with_stdio(false); cin.tie(0); cout.tie(0)
template<class T> inline T qmin(T a, T b) { return a < b ? a : b; }
template<class T> inline T qmax(T a, T b) { return a > b ? a : b; }
typedef long long ll;
typedef unsigned long long ull;
const db eps = 1e-9;
const db PI = acos(-1);
const int inf = 0x3f3f3f3f;
const int mod = 998244353;
const int maxn = (int)2e5 + 5;//remember to modify it, No RE or MLE
const ll INF = 0x3f3f3f3f3f3f3f3f;
using namespace std;
int n, m, k;
PII p[maxn];
int tot = 0;
set<int> s;
int dp[1<<10], bit[1<<10], pos[maxn];
int lg[10];
void init(){
rep(i, 0, 8) lg[i] = 1 << i;
}
int main()
{
init();
scanf("%d %d %d", &n, &m, &k);
rep(i, 1, n){
int l, r; scanf("%d %d", &l, &r);
p[++tot] = mp(l, i);
p[++tot] = mp(r + 1, -i);
}
sort(p + 1, p + tot + 1);
rep(i, 0, k - 1) s.insert(i);
rep(i, 0, lg[k]-1) dp[i] = -inf, bit[i] = bit[i>>1] ^ (i & 1);
dp[0] = 0;
int last = 0, now, x;
rep(i, 1, tot){
now = p[i].fi, x = p[i].se;
rep(j, 0, lg[k]-1) dp[j] += bit[j] * (now - last);
last = now;
if(x > 0){
pos[x] = *s.begin(); s.erase(pos[x]);
rep(j, 0, lg[k]-1){
if(j & lg[pos[x]]) dp[j] = qmax(dp[j], dp[j^lg[pos[x]]]);
}
} else {
x = -x;
s.insert(pos[x]);
rep(j, 0, (1<<k)-1){
if(j & lg[pos[x]]){
dp[j^lg[pos[x]]] = qmax(dp[j^lg[pos[x]]], dp[j]), dp[j] = -inf;
}
}
}
}
printf("%d\n", dp[0]);
return 0;
}