【扫描线法】&& poj 1177 && hdu 1828

    

      可以看看这里: http://www.cnblogs.com/Booble/archive/2010/10/10/1847163.html

      为了写扫描线, 大概写了有史以来最丑的线段树了。


      poj 1177 && hdu 1828 都是求矩形周长并,周长并改一改就可以求面积并了。

      其实思想并不复杂,将x维排序,将x维上的2n条线段作为事件,每个事件统计与上个事件之间的所占周长长度。


      统计周长长度有点烦, 在y维上要用线段树维护: 共有多长的线段被覆盖,以及共有多少“团”线段。


      每次加的答案就是 : 覆盖值得改变量 + (当前线段与前一线段的距离) * 2 * (线段"团"数);

 

      至于线段树,离散之后我维护了六个标记(貌似有神犇只要用三个标记+.+),而且合并的时候写的十分丑陋;


      维护了这么六个值: 该区间覆盖最小值,最小值是否在左区间/右区间,最小值出现次数以及团数,以及为了维护最小值而保留的另一个标记。


     反正就是很丑,写了5KB,难得有线段树写的这么丑。


# include <cstdio>
# include <cstdlib>
# include <cmath>
# include <cstring>

using namespace std;

const int maxn = 7000;
int len[maxn*2], old[maxn*2],left[maxn], right[maxn], low[maxn],high[maxn];
int newlow[maxn], newhigh[maxn], num[maxn*2], id[maxn*2];
int bj[maxn*4], tmin[maxn*4], tot[maxn*4], repeat[maxn*4];
bool covl[maxn*4], covr[maxn*4];

int top, mat, ans, h, st, n, i;
 
void sort(int l, int r)
{
	int i = l, j = r, d = num[(l + r) >> 1], dj = id[(l + r) >> 1] % 2,tmp;
	for (;i <= j;)
	{
		for (;(num[i] < d) || (num[i] == d && (id[i] % 2) < dj);i++);
		for (;(num[j] > d) || (num[j] == d && (id[j] % 2) > dj);j--);
		if (i <= j)
		   tmp = num[i], num[i] = num[j], num[j] = tmp,
		   tmp = id[i], id[i] = id[j], id[j] = tmp, i++, j--;
	}
	if (i < r) sort (i, r);
	if (l < j) sort (l, j);
}

void prepare_y()
{
	int i; mat = 1,  top = 0;
	for (i = 1; i <= n; i++)
	{
		num[++top] = low[i], id[top] = i * 2;
		num[++top] = high[i], id[top] = i * 2 +1; 
	}
	sort(1, top);
	for (i = 1; i <= top; i++)
	{
		if (num[i] != num[i - 1]) mat++;
		if ((id[i] & 1) == 0 ) newlow[id[i] >> 1] = mat, old[mat] = low[id[i] >> 1];
		else newhigh[id[i] >> 1] = mat, old[mat] = high[id[i] >> 1]; 
	}
	for (h = 0, st = 1; st <= mat + 1; st <<= 1, h ++);
	for (i = 1; i <= st * 2; i++) len[i] = 1; 
	for (i = 1; i <= mat-1; i++) len[st + i] = old[i+1] - old[i];
	for (i = st-1; i>=1; i--) len[i] = len[i << 1]+ len[(i << 1)+1];
	memset(id, 0, sizeof(id));
	memset(num, 0, sizeof(num));
}

void prepare_x()
{
	top = 0;
	for (i = 1; i <= n; i++)
	{
		num[++top] = left[i], id[top] = i * 2;
		num[++top] = right[i], id[top] = i * 2 +1;
	}
	sort(1, top);
}

void origin()
{
	memset(bj, 0, sizeof(bj));
	memset(tmin, 0, sizeof(tmin));
	memset(covl, true, sizeof(covl));
	memset(covr, true, sizeof(covr));
	for (int i = 1; i <= st * 2; i++) 
	   repeat[i] = 1, tot[i] = 1;
	for (int i = 1; i <= mat; i++)
	   tot[i +st] = len[i+st];
	for (int i = st - 1; i >= 1; i--)
	   tot[i] = tot[i << 1] + tot[(i << 1 )+1];
}

int min(int x, int y)
{
	return x < y ? x: y;
}

void up(int x)
{
	for (; x>= 1; x >>=1)
	{
		tmin[x] = min(tmin[x << 1], tmin[(x << 1) +1]);
		if (tmin[x << 1] == tmin[(x << 1) +1])
		{
			repeat[x] = repeat[x << 1] + repeat[(x << 1) +1] - (covr[x << 1] && covl[(x << 1)+1]);
			tot[x] = tot[x << 1] + tot[(x << 1 )+1];
			covl[x] = covl[x << 1], covr[x] = covr[(x << 1) +1]; 
		}
		else if (tmin[x << 1] < tmin[(x << 1) +1])
		{
			repeat[x] = repeat[x << 1];
			tot[x] = tot[x << 1];
			covl[x] = covl[x << 1], covr[x] = false;
		}
		else
		{
			repeat[x] = repeat[(x << 1)+1];
			tot[x] = tot[(x << 1) +1];
			covr[x] = covr[(x << 1)+1]; covl[x] = false;
		}
	}
}

void down(int x)
{
    int i, now;
    for (i = h; i>0; i--)
    {
		now = x >> i;
		if (bj[now] != 0) 
		{
			bj[now << 1]+= bj[now], bj[(now << 1) +1]+= bj[now];
			tmin[now << 1]+= bj[now], tmin[(now << 1)+1]+= bj[now];
			bj[now]= 0; 
		} 
	}
}

void change(int l, int r, int d)
{
	l = l+st-1, r = r+st+1;
	int ll = l >> 1, rr = r >> 1;
	down(l); down(r);
	for (;(l ^ r) != 1; l >>= 1, r >>= 1)
	{
		if ((l & 1) == 0) bj[l+1]+=d, tmin[l+1]+=d;
		if ((r & 1) == 1) bj[r-1]+=d, tmin[r-1]+=d;
	}
	up(ll); up(rr); 
}

void help()
{
    for (int i = 1; i <= st; i++)
       down(i+st);
}

int main()
{
	freopen("1177.in", "r", stdin);
	freopen("1177.out", "w", stdout);
	while (scanf("%d", &n) != EOF)
	{
	for (i = 1; i <= n; i++)
	   scanf("%d%d%d%d", &left[i], &low[i], &right[i], &high[i]);
	prepare_y();
	prepare_x();
	origin();
	ans = high[id[1] >> 1] - low[id[1] >> 1];
	change(newlow[id[1] >> 1], newhigh[id[1] >> 1]-1, 1);
	for (i = 2; i <= top; i++)
	{
	 	//help();
		int who = id[i] >> 1;
		int a1 = len[1]- tot[1] , a2 = repeat[1];
		if ((who << 1)== id[i]) change(newlow[who], newhigh[who]-1, 1);
		else change(newlow[who], newhigh[who]-1, -1);
		int b1 = len[1]- tot[1] ;
		ans += abs(a1 - b1) + (num[i] - num[i-1]) * 2 * (a2 - 1); 
	}
	printf("%d\n", ans);
    }
	return 0;
}

ps: hdu上居然是多组数据,贡献了六七个wa。


附带一个poj1151 求矩形面积并的, 稍微好些一点;

# include <cstdlib>
# include <cstdio>
# include <cmath>
# include <cstring>

using namespace std;

const int maxn = 200;
int  id[maxn];
double num[maxn], left[maxn], right[maxn], low[maxn], high[maxn], old[maxn*2], tot[maxn*4], len[maxn*4];
int  tmin[maxn*4],  bj[maxn*4], newlow[maxn], newhigh[maxn];
int  test, h, st, n, top, mat;
double ans;

void sort(int l, int r)
{
	double d = num[(l + r)>> 1], tmpd;
	int i = l, j = r, tmp,  dj = id[(l + r)>> 1] & 1;
	for (;i <= j;)
	{
		for (;num[i] < d || (num[i] == d && (id[i] & 1) < dj); i++);
        for (;num[j] > d || (num[j] == d && (id[j] & 1) > dj); j--);
		if (i <= j) 
		   tmpd=num[i], num[i]=num[j], num[j]=tmpd,
		   tmp=id[i], id[i]=id[j], id[j]=tmp, i++,j--;	
	}
	if (i < r) sort(i, r);
	if (l < j) sort(l, j); 
}

void prepare_y()
{
	memset(num, 0, sizeof(num));
	memset(id, 0, sizeof(id));
	int i; top = 0; mat = 1;
	for (i = 1; i <= n; i++)
	{
		num[++top] = low[i]; id[top] = i * 2;
		num[++top] = high[i]; id[top] = i * 2 + 1;
	}
	sort(1, top);
	for (i = 1; i <= top; i++)
	{
		if (num[i] != num[i-1]) mat++;
		if ((id[i] & 1) == 0) newlow[id[i] >> 1] = mat, old[mat] = low[id[i] >> 1];
		else newhigh[id[i] >> 1] = mat, old[mat] = high[id[i] >> 1]; 
	}
	for (st = 1, h = 0; st <= mat +1; st <<= 1, h++);
	for (i = 1; i <= st*2; i++) len[i] = 1;
	for (i = 1; i <= mat-1; i++) len[i+st] = old[i+1] - old[i];
	for (i = st-1; i >= 1; i--) len[i] = len[i << 1] + len[(i << 1)+1];
}

void prepare_x()
{
	memset(num, 0, sizeof(num));
	memset(id, 0, sizeof(id));
	int i; top = 0; mat = 1;
	for (i = 1; i <= n; i++)
	{
		num[++top] = left[i], id[top] = i * 2;
		num[++top] = right[i], id[top] = i * 2 +1;
	}
	sort(1, top);
}

void origin()
{
	int i; ans = 0; 
	memset(tmin, 0, sizeof(tmin));
	memset(bj, 0 ,sizeof(bj));
	for (i = 1; i <= st*2; i++) tot[i] = len[i];
}

void read()
{
	int i; scanf("%d", &n);
	for (i = 1; i <= n; i++)
	  scanf("%lf%lf%lf%lf", &left[i], &low[i], &right[i], &high[i]);
	prepare_y();
	prepare_x();
	origin();
}

void down(int x)
{
	int i;
	for (i = h; i > 0; i--)
	{
		int now = x >> i;
		if (bj[now] != 0)
		{
			bj[now << 1]+= bj[now]; bj[(now << 1)+1]+= bj[now];
			tmin[now << 1]+=bj[now]; tmin[(now << 1)+1]+= bj[now];
			bj[now] = 0; 
		}
	}
}

int min(int x, int y)
{
	return x < y ? x:y ;
}

void up(int x)
{
	for (;x > 0; x >>=1)
	{
		tmin[x] = min(tmin[x << 1], tmin[(x << 1)+1]);
        if (tmin[x << 1] == tmin[(x << 1)+1]) tot[x] = tot[x << 1] + tot[(x << 1)+1];
        else if (tmin[x << 1] < tmin[(x << 1)+1]) tot[x] = tot[x << 1];
        else  tot[x] = tot[(x << 1)+1];
	}
}

void change(int l, int r, int d)
{
	l = l+st-1; r= r+st+1; 
	int ll = l >> 1, rr = r >> 1;
	down(l); down(r);
	for (;(l ^ r) != 1; l>>=1, r>>=1)
	{
		if ((l & 1) == 0) tmin[l+1]+= d, bj[l+1]+= d;
		if ((r & 1) == 1) tmin[r-1]+= d, bj[r-1]+= d;
	}
	up(ll); up(rr);
}

int i; 
int main()
{
	freopen("1151.in", "r", stdin);
	freopen("1151.out", "w", stdout);
	for (test = 1;;test++)
	{
		read();
		if ( n == 0) break;
		change(newlow[id[1] >> 1], newhigh[(id[1]>>1)]-1, 1);
		for (i = 2; i <= top; i++)
		{
			ans += (num[i] - num[i-1]) * (len[1] - tot[1]);
			if ((id[i] & 1) == 0) change(newlow[id[i] >> 1], newhigh[(id[i]>>1)]-1, 1);
			else change(newlow[id[i] >> 1], newhigh[(id[i]>>1)]-1, -1);
		}
		printf("Test case #%d\n", test);
		printf("Total explored area: %.2lf\n\n", ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算 4-5 增强for循环 4-6 数组和排序算章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。
完整版:https://download.csdn.net/download/qq_27595745/89522468 【课程大纲】 1-1 什么是java 1-2 认识java语言 1-3 java平台的体系结构 1-4 java SE环境安装和配置 2-1 java程序简介 2-2 计算机中的程序 2-3 java程序 2-4 java类库组织结构和文档 2-5 java虚拟机简介 2-6 java的垃圾回收器 2-7 java上机练习 3-1 java语言基础入门 3-2 数据的分类 3-3 标识符、关键字和常量 3-4 运算符 3-5 表达式 3-6 顺序结构和选择结构 3-7 循环语句 3-8 跳转语句 3-9 MyEclipse工具介绍 3-10 java基础知识章节练习 4-1 一维数组 4-2 数组应用 4-3 多维数组 4-4 排序算 4-5 增强for循环 4-6 数组和排序算章节练习 5-0 抽象和封装 5-1 面向过程的设计思想 5-2 面向对象的设计思想 5-3 抽象 5-4 封装 5-5 属性 5-6 方的定义 5-7 this关键字 5-8 javaBean 5-9 包 package 5-10 抽象和封装章节练习 6-0 继承和多态 6-1 继承 6-2 object类 6-3 多态 6-4 访问修饰符 6-5 static修饰符 6-6 final修饰符 6-7 abstract修饰符 6-8 接口 6-9 继承和多态 章节练习 7-1 面向对象的分析与设计简介 7-2 对象模型建立 7-3 类之间的关系 7-4 软件的可维护与复用设计原则 7-5 面向对象的设计与分析 章节练习 8-1 内部类与包装器 8-2 对象包装器 8-3 装箱和拆箱 8-4 练习题 9-1 常用类介绍 9-2 StringBuffer和String Builder类 9-3 Rintime类的使用 9-4 日期类简介 9-5 java程序国际化的实现 9-6 Random类和Math类 9-7 枚举 9-8 练习题 10-1 java异常处理 10-2 认识异常 10-3 使用try和catch捕获异常 10-4 使用throw和throws引发异常 10-5 finally关键字 10-6 getMessage和printStackTrace方 10-7 异常分类 10-8 自定义异常类 10-9 练习题 11-1 Java集合框架和泛型机制 11-2 Collection接口 11-3 Set接口实现类 11-4 List接口实现类 11-5 Map接口 11-6 Collections类 11-7 泛型概述 11-8 练习题 12-1 多线程 12-2 线程的生命周期 12-3 线程的调度和优先级 12-4 线程的同步 12-5 集合类的同步问题 12-6 用Timer类调度任务 12-7 练习题 13-1 Java IO 13-2 Java IO原理 13-3 流类的结构 13-4 文件流 13-5 缓冲流 13-6 转换流 13-7 数据流 13-8 打印流 13-9 对象流 13-10 随机存取文件流 13-11 zip文件流 13-12 练习题 14-1 图形用户界面设计 14-2 事件处理机制 14-3 AWT常用组件 14-4 swing简介 14-5 可视化开发swing组件 14-6 声音的播放和处理 14-7 2D图形的绘制 14-8 练习题 15-1 反射 15-2 使用Java反射机制 15-3 反射与动态代理 15-4 练习题 16-1 Java标注 16-2 JDK内置的基本标注类型 16-3 自定义标注类型 16-4 对标注进行标注 16-5 利用反射获取标注信息 16-6 练习题 17-1 顶目实战1-单机版五子棋游戏 17-2 总体设计 17-3 代码实现 17-4 程序的运行与发布 17-5 手动生成可执行JAR文件 17-6 练习题 18-1 Java数据库编程 18-2 JDBC类和接口 18-3 JDBC操作SQL 18-4 JDBC基本示例 18-5 JDBC应用示例 18-6 练习题 19-1 。。。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值