BZOJ 1790: [Ahoi2008]Rectangle 矩形藏宝地

题目传送门

【题目大意】

  游戏的主办方把这块开阔地当作第一象限,将所有可能埋藏宝藏的地方划成一个个矩形的土地,并把这些矩形土地的坐标都告诉了参赛者。挖宝的提示很简单,只要某一个矩阵土地至少被另外一个矩阵土地所包含,那么这个矩阵土地里肯定埋有宝藏。问:有多少个矩形土地里肯定埋有宝藏?

  其实就是求对于矩形i,是否存在一个矩形j,使得aj<ai,bj<bi,cj>ci,dj>di。

  并不要求在线,用离线算法就好了。(CDQ分治)

  先对a排序,取mid,表示i小于等于mid的标记为添加,大于mid的标记为查询。

  再对b排序,保证b是从小到大的,遇到添加的就将c作为下标,存d(线段树维护最大值),查询的就询问c+1~n的最大值是否大于d,是,标记当前矩形为藏宝地,不能直接ans++,会计算重复。

  为什么这是对的?

  因为查询的a一定比添加的a大,又对b进行排序,又保证了b有序。那么查询的矩阵A找到的添加的矩阵B,一定是B.a<A.a,B.b<A.b,剩下的就不解释了……

  这题卡常,排序一定要写好。(TLE了好多次……)

#include<cstdio>
#include<algorithm> #define imax(a,b) ((a>b)?(a):(b)) using namespace std; const int N=200010; int A[N],B[N],C[N],D[N],*Ry,id[N];
struct data{ int id; bool p; } np[N];
int n,px,T[N<<2],ans;
bool vis[N]; void updata(int ro,int L,int R,int x,int val)
{
if(x<L || x>R) return;
if(L==x && R==x)
{
T[ro]=val;
return;
}
int Mid=(L+R)>>1;
updata(ro<<1,L,Mid,x,val); updata(ro<<1|1,Mid+1,R,x,val);
T[ro]=imax(T[ro<<1],T[ro<<1|1]);
} int query(int ro,int L,int R,int li,int ri)
{
if(L>ri || R<li) return 0;
if(li<=L && R<=ri) return T[ro];
int Mid=(L+R)>>1;
int q1=query(ro<<1,L,Mid,li,ri),q2=query(ro<<1|1,Mid+1,R,li,ri);
return imax(q1,q2);
} bool cmp(int a,int b) { return (Ry[a]<Ry[b]); } bool Cmp(data A,data B) { return (Ry[A.id]<Ry[B.id]); } void CDQ(int L,int R)
{
if(L==R) return;
int Mid=(L+R)>>1;
for(int i=L;i<=Mid;i++) np[i].p=1;
Ry=B; sort(np+L,np+R+1,Cmp);
for(int i=L;i<=R;i++)
{
if(np[i].p) updata(1,1,n,C[np[i].id],D[np[i].id]); else
if(query(1,1,n,C[np[i].id]+1,n)>D[np[i].id]) vis[np[i].id]=1;
}
for(int i=L;i<=R;i++) if(np[i].p) updata(1,1,n,C[np[i].id],0),np[i].p=0;
Ry=A; sort(np+L,np+R+1,Cmp);
CDQ(L,Mid); CDQ(Mid+1,R);
} int read()
{
int yu=0;
char ch=getchar();
while(ch>'9' || ch<'0') ch=getchar();
while(ch>='0' && ch<='9')
{
yu=(yu<<3)+(yu<<1)+ch-'0';
ch=getchar();
}
return yu;
} void work()
{
for(int i=1;i<=n;i++) id[i]=i;
sort(id+1,id+1+n,cmp);
for(int i=1;i<=n;i++) Ry[id[i]]=i;
} int main()
{
scanf("%d",&n); ans=0;
for(int i=1;i<=n;i++)
{
A[i]=read(); B[i]=read();
C[i]=read(); D[i]=read();
}
Ry=D; work(); Ry=C; work();
Ry=B; work(); Ry=A; work();
for(int i=1;i<=n;i++) np[i].id=id[i];
CDQ(1,n); for(int i=1;i<=n;i++) if(vis[i]) ans++;
printf("%d\n",ans);
return 0;
}

BZOJ 1790: [Ahoi2008]Rectangle 矩形藏宝地的更多相关文章

  1. [BZOJ1790][AHOI2008]Rectangle 矩形藏宝地(四维偏序,CDQ+线段树)

    1790: [Ahoi2008]Rectangle 矩形藏宝地 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 553  Solved: 193[Subm ...

  2. bzoj1790: [Ahoi2008]Rectangle 矩形藏宝地

    被统考草翻回来做题不太行啊,线段树和cdq都写挂细节 这题大概就是四维偏序吧,欸n怎么到了20w,只能水70啊 但是这个好像只要有1个在里面就可以ans就可以++了耶 突然想到高中奥数老师说的,大概是 ...

  3. 洛谷 P3187 BZOJ 1185 [HNOI2007]最小矩形覆盖 (旋转卡壳)

    题目链接: 洛谷 P3187 [HNOI2007]最小矩形覆盖 BZOJ 1185: [HNOI2007]最小矩形覆盖 Description 给定一些点的坐标,要求求能够覆盖所有点的最小面积的矩形, ...

  4. ●BZOJ 1185 [HNOI2007]最小矩形覆盖

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=1185 题解: 计算几何,凸包,旋转卡壳 结论:矩形的某一条边在凸包的一条边所在的直线上. ( ...

  5. BZOJ 1185: [HNOI2007]最小矩形覆盖-旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标-备忘板子

    来源:旋转卡壳法求点集最小外接矩形(面积)并输出四个顶点坐标 BZOJ又崩了,直接贴一下人家的代码. 代码: #include"stdio.h" #include"str ...

  6. bzoj 1185 [HNOI2007]最小矩形覆盖 凸包+旋转卡壳

    题目大意 用最小矩形覆盖平面上所有的点 分析 有一结论:最小矩形中有一条边在凸包的边上,不然可以旋转一个角度让面积变小 简略证明 我们逆时针枚举一条边 用旋转卡壳维护此时最左,最右,最上的点 注意 注 ...

  7. bzoj 1787 [Ahoi2008]Meet 紧急集合(1832 [AHOI2008]聚会)

    1787: [Ahoi2008]Meet 紧急集合 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 1841  Solved: 857[Submit][ ...

  8. BZOJ 1832: [AHOI2008]聚会( LCA )

    LCA模板题...不难发现一定是在某2个人的LCA处集合是最优的, 然后就3个LCA取个最小值就OK了. 距离就用深度去减一减就可以了. 时间复杂度O(N+MlogN) (树链剖分) -------- ...

  9. BZOJ 1787: [Ahoi2008]Meet 紧急集合( 树链剖分 )

    这道题用 LCA 就可以水过去 , 但是我太弱了 QAQ 倍增写LCA总是写残...于是就写了树链剖分... 其实也不难写 , 线段树也不用用到 , 自己YY一下然后搞一搞就过了...速度还挺快的好像 ...

随机推荐

  1. Centos上运行.net core2.0

    一.在centos7上安装.net core sdk 微软文档:https://www.microsoft.com/net/learn/get-started/linux/centos 二.直接在Ce ...

  2. 修改数组数据头和尾push()、pop()和unshift()、shift()

    1.push().pop()和unshift().shift() 这两组同为对数组的操作,并且会改变数组的本身的长度及内容. 不同的是 push().pop() 是从数组的尾部进行增减,unshift ...

  3. 移动端rem设置(部分安卓机型不兼容)

    (function(win) { var doc = win.document; var docEl = doc.documentElement; var tid; function refreshR ...

  4. 【OpenCV】关于 waitKey()的使用方法

    C++: int waitKey(int delay=0) cvWaitKey()函数的功能是不断刷新图像,频率时间为delay,单位为ms. 返回值为当前键盘按键值. 所以显示图像时,如果需要在cv ...

  5. Http状态码大全(200、404、500等)

    基本涵盖了所有问题 HTTP 400 – 请求无效HTTP 401.1 – 未授权:登录失败HTTP 401.2 – 未授权:服务器配置问题导致登录失败HTTP 401.3 – ACL 禁止访问资源H ...

  6. vue项目中引用echarts的几种方式

    准备工作: 首先我们初始化一个vue项目,执行vue init webpack echart,接着我们进入初始化的项目下.安装echarts, npm install echarts -S //或   ...

  7. 图片放大不失真软件PhotoZoom的工具栏

    PhotoZoom是一款极其简单的图片无损放大工具,简单几即可渲染出完美的放大照片,呈现无与伦比的画质效果.虽然简单,菜单和面板的功能很少,但却是设计师的必备神器,因为其简单易用性,它的软件菜单命令和 ...

  8. Brain Network (hard) CodeForces - 690C 简单倍增 + 一些有趣的推导

    Code: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ...

  9. Linux进程地址管理之mm_struct

    FROM : http://www.cnblogs.com/Rofael/archive/2013/04/13/3019153.html Linux对于内存的管理涉及到非常多的方面,这篇文章首先从对进 ...

  10. HTTPie:一个不错的 HTTP 命令行客户端

    转自:http://top.jobbole.com/9682/ HTTPie:一个不错的 HTTP 命令行客户端 HTTPie (读aych-tee-tee-pie)是一个 HTTP 的命令行客户端. ...