hdu 1264 线段树+扫描线

说实话  真是水题   题目给的数据太小  都不用离散化      之前用离散化处理一个类似的题

这道题是给你几个矩形    让你求覆盖面积    重复的只算一次

做完之后被坑了        题目说输入左下角和右下角坐标    但是     左上角和右下角也有可能   只要是对角就行    所有得线处理一下

#include<stdio.h>

#include<iostream>

#include<algorithm>

#include<string.h>

using namespace std;

#define LL(x) (x<<1)

#define RR(x) ((x<<1)|1)

struct node

{

int y,x1,x2;

int flash;

}A[2*5000];

int num[110*4];

int Min(int a,int b)

{

return a<b?a:b;

}

int Max(int a,int b)

{

return a>b?a:b;

}

int cmp(node a,node b)

{

return a.y<b.y;

}

int update(int L,int R,int left,int right,int mark,int k)

{

int mid=(L+R)/2;

if(L==left&&right==R)

{

if(num[mark]>=0)

{

num[mark]+=k;

}

else

{

update(L,mid,L,mid,LL(mark),k);

update(mid,R,mid,R,RR(mark),k);

if(num[LL(mark)]==num[RR(mark)]) num[mark]=num[LL(mark)];

}

}

else

{

if(num[mark]>=0)

{

num[LL(mark)]=num[mark];

num[RR(mark)]=num[mark];

}

if(right<=mid)

{

update(L,mid,left,right,LL(mark),k);

}

else if(left>=mid)

{

update(mid,R,left,right,RR(mark),k);

}

else

{

update(L,mid,left,mid,LL(mark),k);

update(mid,R,mid,right,RR(mark),k);

}

if(num[LL(mark)]==num[RR(mark)]) num[mark]=num[LL(mark)];

else num[mark]=-1;

}

return 0;

}

int find(int L,int R,int mark)

{

int dis=0;

int mid=(L+R)/2;

if(num[mark]==0) return 0;

if(num[mark]>0)

{

dis+=R-L;

return dis;

}

dis+=find(L,mid,LL(mark))+find(mid,R,RR(mark));

return dis;

}

int main()

{

int x1,y1,x2,y2;

int i,j;

while(~scanf("%d%d%d%d",&x1,&y1,&x2,&y2))

{

if(x1==-2) break;

i=1;

while(1)

{

A[i].y=Min(y1,y2);

A[i].x1=A[i+1].x1=Min(x1,x2);

A[i].x2=A[i+1].x2=Max(x1,x2);

A[i+1].y=Max(y1,y2);

A[i].flash=1;

A[i+1].flash=-1;

scanf("%d%d%d%d",&x1,&y1,&x2,&y2);

if(x1<0) break;

i+=2;

}

i++;

sort(A+1,A+1+i,cmp);

memset(num,0,sizeof(num));

int area=0,a,b;

a=A[1].x1;

b=A[1].x2;

update(0,100,a,b,1,1);

for(int j=2;j<=i;j++)

{   //printf("^^^^\n");

a=A[j].x1;

b=A[j].x2;

area+=(A[j].y-A[j-1].y)*find(0,100,1);

if(A[j].flash==1)

{

update(0,100,a,b,1,1);

}

else

{

update(0,100,a,b,1,-1);

}

}

printf("%d\n",area);

if(x1==-2) break;

}

return 0;

}

时间: 2024-10-13 16:04:53

hdu 1264 线段树+扫描线的相关文章

HDU 5107 线段树扫描线

给出N个点(x,y),每个点有一个高度h 给出M次询问,问在(x,y)范围内第k小的高度是多少,没有输出-1 (k<=10) 线段树扫描线 首先离散化Y坐标,以Y坐标建立线段树 对所有的点和询问进行离线操作,将询问和点按照x,y的大小排序,从左向右,从下向上,对于相同的(x,y)插入点在询问点之前 线段树的每个节点维护10个高度,每次询问[0,mark[i].y]的第mark[i].h高的值即可 #include "stdio.h" #include "string.h

hdu 1255(线段树 扫描线) 覆盖的面积

http://acm.hdu.edu.cn/showproblem.php?pid=1255 典型线段树辅助扫描线,顾名思义扫描线就是相当于yy出一条直线从左到右(也可以从上到下)扫描过去,此时先将所有的横坐标和纵坐标排序 因为是从左到右扫描,那么横坐标应该离散化一下 当扫描线依次扫描的时候,依次扫描到的纵区间在线段树中查找,依据是上边还是下边记录,上边就是-1,下边就是+1, 如果某区间记录值为0的时候,代表没有被覆盖,为1的时候代表覆盖一次,为2代表覆盖两次(不会出现为负数的情况) 最后将依

hdu 1542 线段树+扫描线

啦啦啦~继续学算法 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7349    Accepted Submission(s): 3231 Problem Description There are several

HDU 5091 线段树扫描线

给出N个点,和一个w*h的矩形 给出N个点的坐标,求该矩形最多可以覆盖多少个点 对每个点point(x,y)右边生成对应的点(x+w,y)值为-1: 纵向建立线段树,从左到右扫描线扫一遍,遇到点则用该点的权值更新区间(y,y+h) #include "stdio.h" #include "string.h" #include "algorithm" using namespace std; struct Mark { int x,y,s; }ma

HDU 1542 线段树+扫描线+离散化

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8327    Accepted Submission(s): 3627 Problem Description There are several ancient Greek texts that contain descriptions of the fabled is

HDU 2461 线段树扫描线

给出N个矩形,M次询问 每次询问给出R个,问这R个矩形围成的面积 经典扫面线求面积并,对每次询问的R个点离散化一下 #include "stdio.h" #include "string.h" #include "algorithm" #include "map" using namespace std; map<int,int>mp; struct P { int x1,y1,x2,y2; }p[21]; str

HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)

Problem A : Counting Squares From:HDU, 1264 Problem Description Your input is a series of rectangles, one per line. Each rectangle is specified as two points(X,Y) that specify the opposite corners of a rectangle. All coordinates will be integers in t

HDU 3642 线段树+离散化+扫描线

题意:给你N个长方体的左下角和右上角坐标,问你空间中有多少体积是被大于两个不同的立方体覆盖的.x,y~10^6 z~500 考虑到给的z比较小,所以可以直接枚举z,然后跑二维的扫描线就好. 关于处理被不同的线段覆盖三次的问题,可以维护四个信息,cnt,once,twice,more,然后相互推出结果就好. #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #

HDU 1828 Picture 线段树+扫描线

题意:给你一些矩形的左上角点的坐标和右下角点的坐标,求周长并 最显而易见的思路就是对于x轴和y轴做两次扫描线,对于负数的坐标进行离散化.每次增加的值是线段变化量的绝对值.具体写法和求面积并的差不多. #include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; #define lson rt << 1 , l , m