Gym - 101808E Floods ACM ICPC, Damascus University Collegiate Programming Contest(2018)-E

传送门:http://codeforces.com/gym/101808/problem/E

E-Floods

You probably heard and even saw the heavy rains that flooded the streets of Damascus recently.

Shahhoud is wondering if he should go to university or not. He asked you to find out how much rainwater is filling his street.

To make things simple, you can imagine Shahhoud's street as a 2D polyline consisting of N points. A 2D polyline is a number of points such that every point is connected to the point before it by a line segment. It is guaranteed that any vertical line crosses the polyline in at most one point.

Rain falls from above the polyline down the y axis. Your task is to calculate the total area that keeps rainwater.

The image below describes the second sample test:

 

Input

The first line contains a single integer T, the number of test cases.

Each test case starts with a line containing one integer N (1 ≤ N ≤ 105), the number of points in the polyline that represents the street Shahhoud lives in.

The following N lines describe the points of the polyline. The ith line contains two space separated integers xi and yi, the ith point of the polyline. (0 ≤ xi, yi ≤ 106). It is guaranteed that xi < xi + 1 for every 1 ≤ i < N.

Output

For each test case, print one line containing the total area that keeps rainwater.

Your answer will be considered correct if the relative error is less than 10 - 6.

Example

Input

2
2
1 1
2 1
7
1 1
2 0
3 1
5 5
7 2
8 3
9 0

Output

0.00000000
1.83333333

题意:给n个x坐标递增的点,求如图那样可以积水的阴影面积。

思路:看左边的图,可以考虑把每个水坑分割成三角形或者是梯形。s1的计算方法看右图,假设当前你在看x2,y2这个点,你发现x1这个点比它低,但是sta那个点限制了高度,阴影面积的计算:竖着的很好算,sta的y去-y1。横着的取大的三角形x1-x2,再乘以(y-y1)/(y2-y1)。s2和s3计算方法很朴素,就是当前计算的两个点的x差值,再乘以 限制的sta的y分别减去两个点的高度再相加(梯形里就是上底加下底),最后/2.那么接下来最后的问题就是怎么求每次切割的限制高度sta了,分别统计每个点左边最高点的y和右边最高点的y,每次取较小的那个,记为sta_y。如果这个点高度比当前读的点和下一个点都高,那就可以求s3那样的三角形,或者s2那样的矩形,如果是在两个点之间,那就是s1那种相似的计算啦。

代码:

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<vector>
#include<set>
#include<queue>
using namespace std;
const int maxv = 1e5 + 5;

double ans = 0;
int t, n, x[maxv], y[maxv], l[maxv], r[maxv];

int main()
{
	ios::sync_with_stdio(false);
	//经大佬提醒,G++不关同步会T,大家要养成用cin和cout关同步的好习惯哦
	cin >> t;
	while (t--)
	{
		cin >> n;
		for (int i = 1; i <= n; i++)
			cin >> x[i] >> y[i];
		int maxx = -1;
		for (int i = 1; i <= n; i++)
		{
			maxx = max(maxx, y[i]);
			l[i] = maxx;
		}
		maxx = -1;
		for (int i = n; i >= 1; i--)
		{
			maxx = max(maxx, y[i]);
			r[i] = maxx;
		}
		ans = 0;
		for (int i = 1; i <= n - 1; i++)
		{
			int down, up;
			if (y[i] <= y[i + 1])
			{
				down = i;
				up = i + 1;
			}
			else
			{
				down = i + 1;
				up = i;
			}
			int sta = min(l[down], r[down]);
			if (sta >= y[down] && sta >= y[up])
			{
				ans += (double)(x[i + 1] - x[i])*(double)(2 * sta - y[down] - y[up])*0.5;
			}
			else if (sta > y[down])
			{
				ans += (double)(x[i + 1] - x[i])*(double)(sta - y[down])*(double)(sta - y[down]) / (y[up] - y[down])*0.5;
			}
		}
		printf("%.8lf\n", ans);

	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值