codeforces 70D 动态凸包

http://www.codeforces.com/problemset/problem/70/D

两种操作

1:增加一个点,会形成一个新的凸包

2:判断某个点是否在凸包内


有两种方法可以做,不过都类似的,都是根据求凸包的方法来做的。

比如,用水平序求凸包的时候,会有两条凸线,一条上凸折线,一条下凸折线,那么判断一个点在这个凸包内就是判断这个点是否在上凸折线的下方以及是否在下凸折线的上方


如上图所示是一条下凸折线,新增点now在折线的下方,即在凸包外部,所以要找到水平序相邻的两个点p x,然后左边从p开始,利用叉积判断不断的删点,右边类似。。最后两条红色的线就是新的凸包的边,p q x 由于now这个点的加入而被删除了。

加入一个点的时候,我们需要找到凸线上水平序相邻的两个点,然后向两边不停的删点,直到满足凸包的定义为止

找到相邻的两个点可以用平衡树,用stl的话会简便很多很多。

注:一个小细节,传参数的时候没加引用,直接TLE了

#include <cstdio>
#include <map>
#include <algorithm>
using namespace std;
typedef pair<int, int> pii;
typedef long long lld;
#define MP make_pair
#define X first
#define Y second
map<int, int> Convex[2];
map<int, int>::iterator p , it , it1 , it2 ,q;
lld cross(pii a, pii b, pii c) {
	return (lld) (b.X - a.X) *(c.Y - a.Y) - (lld) (b.Y - a.Y) *(c.X - a.X);
}
bool judge(map<int, int> &st, int x, int y) {
	if (!st.size())    return false;
	if (st.find(x) != st.end())  return y >= st[x];
	if (x < st.begin()->X || (--st.end())->X < x)   return false;
	p = st.lower_bound(x);
	q = p;  q --;
	return cross(MP(x, y), *q, *p) >= 0;
}
void insert(map<int, int> &st, int x, int y) {
	if (judge(st, x, y))   return; 
	st[x] = y;
	p = st.upper_bound(x);
	it1 = it2 = it = p; it-- ; 
	it1 = it;  it1--;  it2 = it1; it2--;
	if(p != st.end() ){
	    q = p; q++;
		while(q != st.end() && cross(MP(x,y),*q,*p) >= 0)	{
			st.erase(p);	p = q;	q ++;
		}
	}
	if(it == st.begin() || it1 == st.begin()) return ;
	while(it1 != st.begin() && cross(MP(x,y),*it1,*it2) >= 0){
		st.erase(it1);  it1 = it2 ;  	it2 --;
	}
}
int main() {
	int Q, op, x, y;
	scanf("%d", &Q);
	while (Q--) {
		scanf("%d%d%d", &op, &x, &y);
		if (op == 1) {
			insert(Convex[0], x, y);
			insert(Convex[1], x, -y);
		} else {
			bool ans1 = judge(Convex[0], x, y) ;
			bool ans2 = judge(Convex[1], x, -y);
			if (ans1 && ans2)
				puts("YES");
			else
				puts("NO");
		}
	}
	return 0;
}


  • 21
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Codeforces动态规划题单中,有基础DP、优化递推式、进阶DP、数据结构、优先队列、并查集、图论、最短路、最小生成树、数论、二分搜索等不同类型的题目。 代码中的内容是一个动态规划的例子,它采用了一个二维数组来存储中间结果,并通过递推的方式计算最优解。这个例子中,它使用了一个for循环嵌套来遍历数组,并利用状态转移方程更新数组中的值。最后输出的是计算得到的最优解。 要注意的是,这段代码是一个完整的程序,需要依赖于一些特定的输入数据才能正确运行。如果你想在Codeforces上找到更多的动态规划题目,可以访问它们的官方网站并浏览题库。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [牛客练习_21314:codeforces (动态规划+01背)](https://blog.csdn.net/qq_45750296/article/details/109587967)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [leetcode双人赛-acm-challenge-workbook:acm-挑战-工作簿](https://download.csdn.net/download/weixin_38701340/19923844)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Codeforces Round #750 (Div. 2)E题(动态规划)](https://blog.csdn.net/m0_51506743/article/details/121083708)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值