线段相交的异或值 (线段树 or 优先队列)
VVQ 最近迷上了线段这种东西
现在他手上有 n 条线段,他希望在其中找到两条有公共点的线段,使得他们的异或值最大。 定义线段的异或值为它们并的长度减他们交的长度
输入描述:
第一行包括一个正整数 n,表示 VVQ 拥有的线段条数。
接下来 n 行每行包括两个正整数 l,r,表示 VVQ 拥有的线段的 左右端点。
输出描述:
一行一个整数,表示能得到的最大异或值
输入
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 优先队列)的更多相关文章
- 【计算几何初步-线段相交】【HDU1089】线段交点
You can Solve a Geometry Problem too Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/3 ...
- 判断直线与线段相交 POJ 3304 Segments
题意:在二维平面中,给定一些线段,然后判断在某直线上的投影是否有公共点. 转化,既然是投影,那么就是求是否存在一条直线L和所有的线段都相交. 证明: 下面给出具体的分析:先考虑一个特殊的情况,即n=1 ...
- hdu 1086(判断线段相交)
传送门:You can Solve a Geometry Problem too 题意:给n条线段,判断相交的点数. 分析:判断线段相交模板题,快速排斥实验原理就是每条线段代表的向量和该线段的一个端点 ...
- poj 3304 判断是否存在一条直线与所有线段相交
Segments Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8579 Accepted: 2608 Descript ...
- BZOJ 4777 Usaco2017 Open Switch Grass Kruskal+替罪羊树+权值线段树
这道题首先可以看出答案一定是一条边,而且答案一定在最小生成树上,那么我们就可以在这个最小生成树上维护他与异色儿子的边最小值,所以我们就可以已通过Kruskal和一棵平衡树来解决,时间复杂度是O(n*l ...
- 【bzoj3065】带插入区间K小值 替罪羊树套权值线段树
题目描述 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理性愉悦一下,查询区间k小值.他每次向它的随从伏特提出 ...
- 【BZOJ3065】带插入区间K小值 替罪羊树+权值线段树
[BZOJ3065]带插入区间K小值 Description 从前有n只跳蚤排成一行做早操,每只跳蚤都有自己的一个弹跳力a[i].跳蚤国王看着这些跳蚤国欣欣向荣的情景,感到非常高兴.这时跳蚤国王决定理 ...
- 【BZOJ4605】崂山白花蛇草水 权值线段树+kd-tree
[BZOJ4605]崂山白花蛇草水 Description 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了 ...
- 【bzoj4605】崂山白花蛇草水 权值线段树套KD-tree
题目描述 神犇Aleph在SDOI Round2前立了一个flag:如果进了省队,就现场直播喝崂山白花蛇草水.凭借着神犇Aleph的实力,他轻松地进了山东省省队,现在便是他履行诺言的时候了.蒟蒻Bob ...
随机推荐
- Vue 父组件与子组件的传值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- UPC 2019年第二阶段我要变强个人训练赛第六场
传送门 A.上学路线 题目描述 小D从家到学校的道路结构是这样的:由n条东西走向和m条南北走向的道路构成了一个n*m的网格,每条道路都是单向通行的(只能从北向南,从西向东走). 已知小D的家在网格的左 ...
- 2018-9-20-断点调试-Windows-源代码
title author date CreateTime categories 断点调试 Windows 源代码 lindexi 2018-09-20 17:37:55 +0800 2018-05-1 ...
- P1026 翻硬币
题目描述 小明正在玩一个"翻硬币"的游戏.桌上放着排成一排的若干硬币.我们用 * 表示正面,用 o 表示反面(是小写字母,不是零). 比如,可能情形是:**oo***oooo 如果 ...
- Jquery Validate表单验证,自定义校验正整数
// 添加自定义校验规则,校验正整数 jQuery.validator.addMethod("positiveinteger", function(value, element) ...
- 【2016常州一中夏令营Day1】
Problem 1. suffix给定一个单词,如果该单词以 er. ly 或者 ing 后缀结尾,则删除该后缀(题目保证删除后缀后的单词长度不为 0),否则不进行任何操作.Input输入一行,包含一 ...
- 学习Java第七周
重要知识点 1.“super”的用法 构造器和方法,都用关键字super指向超类,但是用的方法不一样.方法用这个关键字去执行被重载的超类中的方法 2.接口和抽象类的异同 相同: 1.接口和抽象类都有抽 ...
- http、https、SSL、TLS的区别
一.HTTP和HTTPS之间的区别 HTTP是一种协议,全称叫作:超文本传输协议(HTTP,HyperText Transfer Protocol),是互联网上应用最为广泛的一种网络协议.所有的WWW ...
- springboot 文件上传及java使用post请求模拟文件上传
参考自:https://blog.csdn.net/qq_25958999/article/details/83988974 接收端Controller类中方法: @RequestMapping(va ...
- socket粘包问题及解决方案
一.粘包问题 问题1: 无法确认对方发送过来数据的大小. 'client.py' import socket client = socket.socket() client.connect( ('12 ...