solution:
考点:数学 + 2-sat 模型。
观察 k≤4k\leq 4k≤4 肯定有猫腻。
设所有正方形的右边界最小值为 mnxmnxmnx 。
则可以证明若有解一定存在一个竹签使得其纵坐标为 mnxmnxmnx ,即调整坐标得到不劣的方案。
类似的也有同样的性质。对于 k≤3k\leq 3k≤3 的情况,根据鸽巢原理,一定存在一个竹签落在四个角上。直接 O(4kn)O(4^kn)O(4kn) 爆搜即可。
对于 k=4k=4k=4 的情况,正确考虑方式为:如果一个矩形如果和三条直线相交,那么一定包含一条边界,可以不用考虑;否则考虑 2-sat 模型。限制条件为:若两个区间不存在交,则一定不能被同一条边覆盖。
那我们可以把 l, r 端点分别 push_back 进每一个可能满足的边,对于每个 l, 向满足 r<l 的点建边,同理,对于每个 r,向满足 l>r 的点建边。可以 two-pointers 完成。这样要构造 2*3=6 倍节点。
时间复杂度 O(n(logn+4k))O(n(logn+4^k))O(n(logn+4k)) 。代码好恶心。
代码是 zyyzyyzyy 的,做了一些改动。debugdebugdebug 了一晚上终于改对了代码。
#include <bits/stdc++.h>
#define PII pair<int,int>
#define INF 0x3f3f3f3f
#define ll long long
#define fi first
#define se second
#define For(i,j,k) for (int i=(int)(j);i<=(int)(k);i++)
#define Rep(i,j,k) for (int i=(int)(j);i>=(int)(k);i--)
using namespace std;
const int mx = 2e5 + 5;
const int mxn = mx * 6;
int n, k, nd, cnt[mx], id[mx][2], pr[mx], su[mx], at[mx][2];
int dfn[mxn], low[mxn], vis[mxn], c[mxn], s[mxn], tp, bl, num;
struct qry {
int x, v0, v1;
bool operator <(const qry &a) const {
return x < a.x;
}
};
vector<qry> vl[4], vr[4];
vector<int> g[mxn];
PII ans[5]