Description
utsuho 有 n 条线段,现在她希望在其中找到两条有公共点的线段,使得它们的 异或值 最大。
定义线段异或值为它们并的长度减它们交的长度.
Input
从文件 ut.in 中读入数据。
输入的第一行包括一个正整数 n,表示 Utsuho 的线段的个数。
接下来 n 行每行包括两个正整数 l,r,表示 Utsuho 拥有的线段的左右端点。
Output
输出到文件 ut.out 中。
输出一行一个整数,表示能得到的最大异或值。
Sample Input
3
10 100
1 50
50 100
Sample Output
99
思路
-
看数据范围
1<=n<=200000,1<=l<=r<=1e8
,n<=200000推断此题算法应该为O(N)或O(logn) -
分析问题,要求任意有公共点的两条线段的异或值,首先想到两条线段一维的关系:包含,相交;
-
设线段A左右端点为LA,RA,线段B左右端点为LB,RB
-
包含(设B包含在A中):线段异或值=LB-LA+RA-RB
-
相交(设AL<BL):线段异或值=LB-LA-RA+RB
-
同时处理L和R,二维偏序问题,想到先按左端点排序[套路],
-
有相同的LB-LA,求极值转换为求另一部分的极值,又要满足有公共点(即区间极值),想到数据结构线段树
-
可以扫描每一条线段,扫描到就加入线段树,借鉴某些题解的思路,也可以先将所有边加入后二分求极值
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#define maxn 200005
#define inf 0x7fffffff
using namespace std;
int n,temp[maxn],ans;
struct node1{int l,r,val;}e[maxn<<2],d[maxn<<2];
struct fdfdfd{int x,y;}a[maxn];
bool cmp(fdfdfd a,fdfdfd b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
int max(int a,int b){return a>b?a:b;}
void pushup1(int x){e[x].val=min(e[x<<1].val,e[x<<1|1].val);}
void pushup2(int x){d[x].val=max(d[x<<1].val,d[x<<1|1].val);}
void build1(int x,int left,int right)
{
e[x].l=left; e[x].r=right;
if(left==right){e[x].val=a[left].y-a[left].x; return;}
int mid=(left+right)>>1;
build1(x<<1,left,mid); build1(x<<1|1,mid+1,right);
pushup1(x);
}
void build2(int x,int left,int right)
{
d[x].l=left; d[x].r=right;
if(left==right){d[x].val=a[left].y+a[left].x; return;}
int mid=(left+right)>>1;
build2(x<<1,left,mid); build2(x<<1|1,mid+1,right);
pushup2(x);
}
int query1(int x,int left,int right)
{
if(e[x].r<left||e[x].l>right) return inf;
if(left<=e[x].l&&right>=e[x].r) return e[x].val;
return min(query1(x<<1,left,right),query1(x<<1|1,left,right));
}
int query2(int x,int left,int right)
{
if(d[x].r<left||d[x].l>right) return -inf;
if(left<=d[x].l&&right>=d[x].r) return d[x].val;
return max(query2(x<<1,left,right),query2(x<<1|1,left,right));
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i) scanf("%d%d",&a[i].x,&a[i].y);
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;++i) temp[i]=a[i].x;
build1(1,1,n); build2(1,1,n);
for(int i=1;i<=n;++i)
{
int res=upper_bound(temp+1,temp+n+1,a[i].y)-temp-1;
ans=max(ans,a[i].y-a[i].x-query1(1,i,res));
ans=max(ans,query2(1,i,res)-a[i].x-a[i].y);
}
printf("%d
",ans);
return 0;
}