0%

VVQ与线段

题意:求任意两条线段的异或最大值。
定义线段的异或值为它们并的长度减他们交的长度

传送门
题解:有两种情况
1:线段a内部包含线段b 贡献:(a.r-a.l)-(b.r-b.l);
2.线段a与线段b相交 贡献:(a.r+b.l-b.l-b.r);
先根据l进行排序,然后计算贡献即可.

线段树

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include<bits/stdc++.h>
using namespace std;
const int maxn= 200005;
const int INF=0x3fffffff;
int Max[maxn<<2],Min[maxn<<2];

struct node{
int l,r;
friend bool operator <(const node &a,const node &b)
{
return a.l<b.l;
}

}a[maxn];
bool cmp(node a,node b)
{
return a.l<b.l;
}

void build(int p,int l,int r)
{
if(l==r)
{
Max[p]=a[l].l+a[l].r;
Min[p]=a[l].r-a[l].l;
return ;
}
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
Max[p]=max(Max[p*2],Max[p*2+1]);
Min[p]=min(Min[p*2],Min[p*2+1]);

}
int Quary_Max(int l,int r,int p,int x,int y)
{
if(l>y||r<x)return 0;
if(l>=x&&r<=y)return Max[p];
int mid=(l+r)>>1;
return max(Quary_Max(l,mid,p*2,x,y),Quary_Max(mid+1,r,p*2+1,x,y));
}

int Quary_Min(int l,int r,int root,int x,int y)
{
if(l>y||r<x)return INF;
if(l>=x&&r<=y)return Min[root];
int mid=(l+r)>>1;
return min(Quary_Min(l,mid,root*2,x,y),Quary_Min(mid+1,r,root*2+1,x,y));
}
int main()
{
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].l,&a[i].r);
sort(a+1,a+1+n,cmp);
build(1,1,n);
int ans=0;
node tmp;
tmp.r=0;
int l,r;
for(int i=1;i<=n;i++)
{
tmp.l=a[i].l;
l=lower_bound(a+1,a+1+n,tmp)-a; //找到a[j].l>=a[i].l的第一个j
tmp.l=a[i].r;
r=upper_bound(a+1,a+1+n,tmp)-a-1; //找到a[j].l<=a[i].r的最后一个j
if(l>r)continue;
//这样就找到左端点在线段i范围内的所有线段
ans=max(ans,Quary_Max(1,n,1,l,r)-a[i].r-a[i].l);
ans=max(ans,a[i].r-a[i].l-Quary_Min(1,n,1,l,r));
}
printf("%d\n",ans);
return 0;
}
/*
3
1 10
4 11
5 6
8

3
10 100
1 50
50 100
99
*/
-------------本文结束感谢您的阅读-------------