VVQ 最近迷上了线段这种东西

现在他手上有 n 条线段,他希望在其中找到两条有公共点的线段,使得他们的异或值最大。 定义线段的异或值为它们并的长度减他们交的长度

输入描述:

第一行包括一个正整数 n,表示 VVQ 拥有的线段条数。
接下来 n 行每行包括两个正整数 l,r,表示 VVQ 拥有的线段的 左右端点。

输出描述:

一行一个整数,表示能得到的最大异或值
示例1

输入

3
10 100
1 50
50 100

输出

99

说明

选择第二条和第三条,99-0=99

备注:

1<=n<=200000,1<=l<=r<=1e8

题意 : 在坐标轴上面有很多线段,问你所有有公共点的线段的异或值最大是多少?
思路 : 所以线段只有 3 种情况, 1 是不相交, 2是相交, 3是包含,第一种情况的答案是 0, 对于第二种情况 假设2条线段i,j,且靠右的线段是 j,则此情况下的异或值是
rj+lj-(ri+li),将 i 看成是不变的量,让 j线段的值最大即可,线段树维护就可以了, 对于第三种情况,答案是 (rj-lj)-(ri-li),则此时值需要让 ri-rl的值最小即可。
代码示例 :
#define ll long long
const int maxn = 2e5+5;
const int mod = 1e9+7;
const double eps = 1e-9;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
#define lson k<<1
#define rson k<<1|1 struct edge
{
int l, r;
bool operator< (const edge &v)const{
return l < v.l;
}
}pre[maxn]; struct node
{
int l, r;
int mi,ma;
}t[maxn<<2]; void pushup(int k){
t[k].ma = max(t[lson].ma, t[rson].ma);
t[k].mi = min(t[lson].mi, t[rson].mi);
} void build(int l, int r, int k){
t[k].l = l;
t[k].r = r;
if (l == r){
t[k].ma = pre[l].l+pre[l].r;
t[k].mi = pre[l].r-pre[l].l;
return;
}
int mid = (l+r) >> 1;
build(l, mid, lson);
build(mid+1, r, rson);
pushup(k);
}
int sum = 0;
void query(int l, int r, int k){
if (l <= t[k].l && t[k].r <= r){
sum = max(sum, t[k].ma);
return;
}
int m = (t[k].l+t[k].r)>>1;
if (l <= m) query(l, r, lson);
if (r > m) query(l, r, rson);
} void query2(int l, int r, int k){
if (l <= t[k].l && t[k].r <= r){
sum = min(sum, t[k].mi);
return;
}
int m = (t[k].l+t[k].r)>>1;
if (l <= m) query2(l, r, lson);
if (r > m) query2(l, r, rson);
} int main() {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int n; cin >>n;
for(int i = 1; i <= n; i++){
scanf("%d%d", &pre[i].l, &pre[i].r);
}
sort(pre+1, pre+1+n);
build(1, n, 1);
int ans = 0;
edge tem;
for(int i = 1; i <= n; i++){
tem.l = pre[i].l;
int p1 = lower_bound(pre+1, pre+1+n, tem)-pre;
tem.l = pre[i].r;
int p2 = upper_bound(pre+1, pre+1+n, tem)-pre-1;
sum = 0;
//printf("p1 = %d p2 = %d\n", p1, p2);
query(p1, p2, 1);
ans = max(ans, sum-(pre[i].l+pre[i].r));
sum = inf;
query2(p1, p2, 1);
ans = max(ans, pre[i].r-pre[i].l-sum);
}
printf("%d\n", ans);
return 0;
}

方法二 : 优先队列(自己的超时了,先借鉴一个,待更新)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
int n, m; struct P {
int l, r;
bool operator < (const P &t) const {
return l + r > t.l + t.r;
}
} p[maxn]; bool cmp(P a, P b) {
return a.l == b.l ? a.r < b.r : a.l < b.l;
} int main() {
while(~scanf("%d", &n)) {
for(int i = 0; i < n; i++) scanf("%d %d", &p[i].l, &p[i].r);
sort(p, p + n, cmp);
priority_queue<P> q;
priority_queue<P> Q;
q.push(p[0]);
Q.push({p[0].l, -p[0].r});
int ans = 0;
for(int i = 1; i < n; i++) {
while(!Q.empty() && -Q.top().r < p[i].l) Q.pop();
if(!Q.empty() && -Q.top().r > p[i].r) ans = max(ans, -(Q.top().r + Q.top().l) - p[i].r + p[i].l);
Q.push({p[i].l, -p[i].r});
while(!q.empty() && q.top().r < p[i].l) q.pop();
//p中所有点已按l排序,当前点与队列里第一个点不相交,后面的点一定不相交
if(!q.empty()) ans = max(ans, p[i].l + p[i].r - q.top().l- q.top().r);
q.push(p[i]);
}
printf("%d\n", ans);
}
return 0;
}

线段相交的异或值 (线段树 or 优先队列)的更多相关文章

  1. 【计算几何初步-线段相交】【HDU1089】线段交点

    You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/3 ...

  2. 判断直线与线段相交 POJ 3304 Segments

    题意:在二维平面中,给定一些线段,然后判断在某直线上的投影是否有公共点. 转化,既然是投影,那么就是求是否存在一条直线L和所有的线段都相交. 证明: 下面给出具体的分析:先考虑一个特殊的情况,即n=1 ...

  3. hdu 1086(判断线段相交)

    传送门:You can Solve a Geometry Problem too 题意:给n条线段,判断相交的点数. 分析:判断线段相交模板题,快速排斥实验原理就是每条线段代表的向量和该线段的一个端点 ...

  4. poj 3304 判断是否存在一条直线与所有线段相交

    Segments Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8579   Accepted: 2608 Descript ...

  5. BZOJ 4777 Usaco2017 Open Switch Grass Kruskal+替罪羊树+权值线段树

    这道题首先可以看出答案一定是一条边,而且答案一定在最小生成树上,那么我们就可以在这个最小生成树上维护他与异色儿子的边最小值,所以我们就可以已通过Kruskal和一棵平衡树来解决,时间复杂度是O(n*l ...

  6. 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树

    题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...

  7. 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树

    [BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...

  8. 【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree

    [BZOJ4605]崂山白花蛇草水 Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了 ...

  9. 【bzoj4605】崂山白花蛇草水 权值线段树套KD-tree

    题目描述 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob ...

随机推荐

  1. 4-1 自动生成spider模板的命令

    scrapy genspider 爬虫名 爬取得网站url例:scrapy genspider jobble2 blog.jobbole.com

  2. 2018-8-10-UWP-分享用那个图标

    title author date CreateTime categories UWP 分享用那个图标 lindexi 2018-08-10 19:16:52 +0800 2018-2-13 17:2 ...

  3. VisualStudio 使用多个环境进行调试

    在 VisualStudio 2017 支持使用 launchSettings.json 文件定义多个不同的环境进行调试 先给大家一张图看一下效果 可以看到原来的是启动的按钮,现在被我修改为 lind ...

  4. linux下svn清除非版本控制文件的方法

    使用svn status命令,文件名前面显示问好的就是非版本控制的文件

  5. H3C 示例:根据主机地址数划分子网

  6. C# 获取 PC 序列号

    在 C++ 需要使用 GetSystemFirmwareTable 的方法来获得 PC 的序列号,需要写的代码很多,但是在 C# 可以使用 WMI 来拿到序列号 首先是安装 System.Manage ...

  7. C#面试题整理(带答案)

    1.维护数据库的完整性.一致性.你喜欢用触发器还是自写业务逻辑?为什么? 答:尽可能用约束(包括CHECK.主键.唯一键.外键.非空字段)实现,这种方式的效率最好:其次用触发器,这种方式可以保证无论何 ...

  8. js实现防抖,节流

    防抖函数. 将几次操作合并为一次操作进行.设置一个计时器,规定在延迟时间后触发函数,但是在延迟时间内如果再次触发,就会取消之前的计时器.如此,只有最后一次操作能触发.代码如下: function de ...

  9. LDO

    1.出现原因:便携式设备的发展,使得人们对电源的要求越来越高,而以前一直使用的三段稳压电源无法满足需求. 2.特点:内部的PNP管导通压降很小,自耗很低. 3.应用场合: (1)不同电压输出级别的应用 ...

  10. 将 Sidecar 容器带入新的阶段

    作者 | 徐迪.张晓宇 导读:本文根据徐迪和张晓宇在 KubeCon NA 2019 大会分享整理.分享将会从以下几个方面进行切入:首先会简单介绍一下什么是 Sidecar 容器:其次,会分享几个阿里 ...