YYHS-Super Big Stupid Cross(二分+扫描线+平衡树)
题目描述
输入
输出
样例输入
样例输出
提示
题解
这道题可以暴力水过,正解是二分+扫描线+平衡树
网上看到的题解都是暴力的,这里写一下正解的算法
读入的时候我们先把横的和竖的线都找出来,并且存一下每条线的len和两端的位置(如果是横的就记录x1,x2,竖的就记录y1,y2)
然后我们二分答案,每次check的时候,把所有线段都减去2*二分的长度(因为两边都要减)并加到新数组里(横的归横的,竖的归竖的),这里我们还要多加一个id值,在之后能用到,如果某条线段的长度不够了,就不用把这条线加到数组里面了
这里我用th[]记录横的线,ts[]记录竖的线
加到数组中后,我们就开始扫描,扫描到横的线的左端就把这条线的y坐标加入到平衡树上(可以用c++的set),扫描到竖的线就查找lower_bound(这条线的下端点),判断一下找到的值是否<=这条线的上端点,如果扫到横的线的右端就把这条线的y坐标从平衡树上删去
因为坐标的范围很大,我们不能直接枚举坐标,所以我们可以按横的线的左端和右端分别排个序,用L[]和R[]存一下,每次用指针往后找就可以了,至于多加的id值,因为排过序,横的线的次序就打乱了,所以我们在加入到数组后直接用另一个数组把th[]存下来,这样每次查询id的时候就可以找到原来的th[].id了
说了那么多,来看看代码吧(可能会好懂一些)
- #include<algorithm>
- #include<cstdio>
- #include<cstring>
- #include<set>
- #define N 100005
- using namespace std;
- int n,x1,x2,y1,y2,cnt1,cnt2,l,r,ans,nums,numh;
- multiset<int> q;
- typedef set<int>::iterator It;
- struct node{
- int x,l,r,len;
- }s[N],ts[N];
- struct Node{
- int y,l,r,len,id;
- }h[N],th[N],Th[N];
- struct NODE{
- int p,id;
- }L[N],R[N];
- bool cmp(node x,node y){ return x.x<y.x; }
- bool cmp1(Node x,Node y){
- if (x.l!=y.l) return x.l<y.l;
- else return x.r<y.r;
- }
- bool cmp2(Node x,Node y){
- if (x.r!=y.r) return x.r<y.r;
- else return x.l<y.l;
- }
- void pre(int len){
- nums=numh=;
- for (int i=;i<=cnt1;i++)
- if (s[i].len>=*len){
- ts[++nums].x=s[i].x;
- ts[nums].len=s[i].len-*len;
- ts[nums].l=s[i].l+len; ts[nums].r=s[i].r-len;
- }
- for (int i=;i<=cnt2;i++)
- if (h[i].len>=*len){
- th[++numh].y=h[i].y;
- th[numh].len=h[i].len-*len;
- th[numh].l=h[i].l+len; th[numh].r=h[i].r-len;
- th[numh].id=numh;//加入的id值
- }
- memcpy(Th,th,sizeof(th));//用临时数组把th存下来,因为之后th数组会被排序
- }
- bool check(int len){
- q.clear();
- q.insert(1e9);//防止lower_bound找到0
- pre(len);
- sort(ts+,ts++nums,cmp);
- sort(th+,th++numh,cmp1);
- for (int i=;i<=numh;i++)
- L[i].p=th[i].l,L[i].id=th[i].id;//按左端点排序
- sort(th+,th++numh,cmp2);
- for (int i=;i<=numh;i++)
- R[i].p=th[i].r,R[i].id=th[i].id;//按右端点排序
- L[numh+].p=R[numh+].p=ts[nums+].x=1e9;//防止越界
- int x=,y=,z=;
- while (x<=numh||y<=numh||z<=nums){
- int a=,b=,c=;
- if (L[x+a].p<=R[y].p&&L[x+a].p<=ts[z].x){
- q.insert(Th[L[x].id].y);
- a++;
- while (L[x+a-].p==L[x+a].p) q.insert(Th[L[x+a].id].y),a++;//把相同左端点的都加到set中
- }
- if (ts[z+c].x<=L[x].p&&ts[z+c].x<=R[y].p){
- It s=q.lower_bound(ts[z].l);
- if (*s<=ts[z].r) return true;
- c++;
- while (ts[z+c-].x==ts[z+c].x){//查询,意义同上面
- It s=q.lower_bound(ts[z+c].l);
- if (*s<=ts[z+c].r) return true;
- c++;
- }
- }
- if (R[y].p<=L[x].p&&R[y].p<=ts[z].x){
- q.erase(Th[R[y].id].y);
- b++;
- while (R[y+b-].p==R[y+b].p) q.erase(Th[R[y+b].id].y),b++;//删除,意义同上
- }
- x+=a; y+=b; z+=c;//不能直接把指针向后移
- }
- return false;
- }
- int main(){
- scanf("%d",&n);
- for (int i=;i<=n;i++){
- scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
- if (x1>x2) swap(x1,x2);
- if (y1>y2) swap(y1,y2);
- if (x1==x2){
- s[++cnt1].x=x1; s[cnt1].l=y1; s[cnt1].r=y2; s[cnt1].len=y2-y1;
- } else{
- h[++cnt2].y=y1; h[cnt2].l=x1; h[cnt2].r=x2; h[cnt2].len=x2-x1;
- }
- }
- l=; r=1e9; ans=1e9;
- while (l<=r){
- int mid=(l+r)>>;
- if (check(mid)){
- ans=mid; l=mid+;
- } else r=mid-;
- }
- if (ans!=1e9) printf("%d\n",ans);
- else puts("Human intelligence is really terrible");
- return ;
- }
YYHS-Super Big Stupid Cross(二分+扫描线+平衡树)的更多相关文章
- BZOJ.4009.[HNOI2015]接水果(整体二分 扫描线)
LOJ BZOJ 洛谷 又是一个三OJ rank1!=w= \(Description\) (还是感觉,为啥非要出那种题目背景啊=-=直接说不好么) 给定一棵树和一个路径集合(每条路径有一个权值).\ ...
- 【BZOJ4009】[HNOI2015]接水果 DFS序+整体二分+扫描线+树状数组
[BZOJ4009][HNOI2015]接水果 Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果.由于她已经DT FC 了The big black, ...
- BZOJ 4009: [HNOI2015]接水果 (整体二分+扫描线 树状数组)
整体二分+扫描线 树状数组 具体做法看这里a CODE #include <cctype> #include <cstdio> #include <cstring> ...
- 【BZOJ3958】[WF2011]Mummy Madness 二分+扫描线+线段树
[BZOJ3958][WF2011]Mummy Madness Description 在2011年ACM-ICPC World Finals上的一次游览中,你碰到了一个埃及古墓. 不幸的是,你打开了 ...
- [bzoj4009] [HNOI2015]接水果 整体二分+扫描线+dfs序+树状数组
Description 风见幽香非常喜欢玩一个叫做 osu!的游戏,其中她最喜欢玩的模式就是接水果. 由于她已经DT FC 了The big black, 她觉得这个游戏太简单了,于是发明了一个更 加 ...
- 【BZOJ 3958】 3958: [WF2011]Mummy Madness (二分+扫描线、线段树)
3958: [WF2011]Mummy Madness Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 96 Solved: 41 Descripti ...
- 接水果(fruit)——整体二分+扫描线
题目 [题目描述] 风见幽香非常喜欢玩一个叫做 osu! 的游戏,其中她最喜欢玩的模式就是接水果.由于她已经 DT FC 了 The big black,她觉得这个游戏太简单了,于是发明了一个更加难的 ...
- HDU-4417 Super Mario,划分树+二分!
Super Mario 这个题也做了一天,思路是很清晰,不过二分那里写残了,然后又是无限RE.. 题意:就是查询区间不大于k的数的个数. 思路:裸划分树+二分答案.将区间长度作为二分范围.这个是重点. ...
- HDU 4747 Mex【线段树上二分+扫描线】
[题意概述] 一个区间的Mex为这个区间没有出现过的最小自然数,现在给你一个序列,要求求出所有区间的Mex的和. [题解] 扫描线+线段树. 我们在线段树上维护从当前左端点开始的前缀Mex,显然从左到 ...
随机推荐
- JAVA实用案例之邮件发送
最近有朋友问邮件怎么发送,就简单写了个demo,因为懒得找jar包,所以项目是创建的maven工程,具体的maven引用的jar如下: <dependency> <groupId&g ...
- px,em,rem,vw单位在网页和移动端的应用
px: 是网页设计中最常用的单位,然而1px到底是多大长,恐怕没有人能回答上来 它用来表示屏幕设备物理上能显示的最小的一个点,这个点不是固定宽度的,不同设备上点的长度.比例有可能会不同. 假设:你现在 ...
- Linux_window与linux之间文件互传,上传下载
window与linux之间文件互传 运行环境:Centos os7 + win8.1 +putty putty:是一个Telnet,ssh,rlogin,纯tcp以及串行接口连接软件,由于linux ...
- ios 初体验<页面切换>
本章类容:介绍如何新建一个页面,打开另一个页面 1.在前面中,在工程Appdelegate.m 里面程序第一个走的方法,新建一个窗口,视图,控制器,可视化等, 2.然后在ViewController. ...
- redis info 命令详解
详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt119 Redis Info 命令以一种易于理解和阅读的格式,返回关于 Red ...
- Linux-kill命令(11)
kill:指定将信号发送给某个进程,常用来杀掉进程,可以通过ps.top命令来查看进程 在默认情况下: 采用编号为的TERM信号.TERM信号将终止所有不能捕获该信号的进程. 对于那些可以捕获该信号的 ...
- [置顶]
基于FPGA的VGA简易显存设计&NIOS ii软核接入
项目简介 本项目基于Altera公司的Cyclone IV型芯片,利用NIOS II软核,2-port RAM与时序控制模块,实现64*48分辨率的显存(再大的显存板载资源m9k不够用) 实现效果如下 ...
- 字符串和转为Data类型前后几天
以防忘记:SimpleDateFormat 可以设置字符串的格式 package com.apploft.util.lang;import java.text.SimpleDateFormat;imp ...
- 团队作业4——第一次项目冲刺(Alpha版本)2017.4.22
昨天来不及编写,这是4月22日的日志,现在补上. 1.开完站立式会议后的合照 2.任务分解图 3.开会讨论的结果,任务分派 队员 今日进展 明日安排 陈鑫龙 原型设计图分析,设计登陆界面原稿 实现登陆 ...
- 201521123035《Java程序设计》第十二周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 书面作业 将Student对象(属性:int id, String name,int age,doubl ...