传送门
题意: 一维数轴上给定很多线段, 求任意两条相交线段的异或最小值, 定义线段的异或值为它们并的长度减他们交的长度.
思路: 我们随便画出一个样例可得, 对于两条相交直线[l1, r1], [l2, r2], 他们的异或值为(r2+l2) - (r1+l1), 且l2 <= r1 <= r2, 所以很明显可以得出ans = max((r2+l2) - (r1+l1)), 且l2 <= r1 <= r2, 所以我们先对线段排序, r小的在前面, 其次l大的在前面, 所以我们开始枚举每一条线段, 找到与该条线段满足相交要求的r存在的区间范围, 这样再这个区间范围内的r1 + l1的min值就是最优的答案, 维护一个区间最值, 当然用线段树呀, 随便维护下就行了, 然后我们寻找时用二分找, 因为要在结构体数组中二分, 所以要手写二分, 注意边界问题, 即找不到的情况. 然后求区间min值注意不要把当前枚举的这条线段加入计算. 这样算下来的ans是所有没有包含的情况的最优值, 所以我们还要算一遍包含情况下的最优值与ans取一个max值就是答案了. 注意算包含情况时要重新排一次序…… 具体细节请看代码…
AC Code
const int maxn = 2e5+5;
struct node {
int l, r;
}p[maxn];
bool cmp1(node x, node y) {
if (x.r != y.r) return x.r < y.r;
return x.l > y.l;
}
bool cmp2(node x, node y) {
if (x.l != y.l) return x.l < y.l;
return x.r > y.r;
}
int a[maxn];
struct Tree{
int tl, tr;
ll minn;
} tree[maxn*4];
void pushup(int id)
{
tree[id].minn = min(tree[id<<1].minn,tree[id<<1|1].minn);
}
void build(int id,int l,int r)
{
tree[id].tl = l; tree[id].tr = r;
if(l == r){
tree[id].minn = p[l].l + p[l].r;
return ;
}
int mid = (l+r) >> 1;
build(id<<1, l, mid);
build(id<<1|1, mid+1, r);
pushup(id);
}
ll mi;
void query(int id, int ql, int qr)
{
int l = tree[id].tl , r = tree[id].tr;
if(ql <= l && r <= qr) {
mi = min(mi, tree[id].minn);
return ;
}
int mid = (l+r) >> 1 ;
if(ql <= mid) query(id<<1, ql, qr);
if(qr > mid) query(id<<1|1, ql, qr);
}
int n;
int bfind(int x) {
int l = 1, r = n, mid, ans = -1;
while(l <= r) {
mid = (l + r) >> 1;
if (p[mid].r >= x) {
r = mid - 1;
ans = mid;
}
else l = mid + 1;
}
if (ans == -1) ans = n + 1;
return ans;
}
void solve()
{
scanf("%d", &n);
for (int i = 1 ; i <= n ; i ++) {
scanf("%d%d", &p[i].l, &p[i].r);
}
sort(p+1, p+1+n, cmp1);
build(1, 1, n);
ll ans = 0;
for (int i = 1 ; i <= n ; i ++) {
int p1 = bfind(p[i].l), p2 = bfind(p[i].r+1)-1;
if (p1 >= p2) continue;
ll t1, t2;
mi = inf; query(1, p1, i-1); t1 = mi;
mi = inf; query(1, i+1, p2); t2 = mi;
ans = max(ans, p[i].r+p[i].l - min(t1, t2));
}
sort(p+1, p+1+n, cmp2);
node tt = p[1];
for (int i = 2 ; i <= n ; i ++) {
if (p[i].r > tt.r) tt = p[i];
else {
ans = max(ans, 1ll*tt.r - tt.l - p[i].r + p[i].l);
}
}
printf("%lld\n", ans);
}