学习清单-zjhl2
hdu 3842 (平衡树维护凸壳)

hdu 5127(cdq分治+凸包)

zjhl2 posted @ 2016年8月12日 04:31 in with tags CDQ分治 凸包 , 1213 阅读

参考了这篇博客 http://blog.csdn.net/u013912596/article/details/47978791 

 

我的做法:

其实每次询问就是 找一个向量(x,y)使得 (x,y)*(p,q)最大。根据向量点积的性质很容易发现最优的向量肯定在凸包上。

如果没有删除操作,可以用平衡树来维护上凸壳和下凸壳,每次询问二分查找。

这题有删除操作,看了题解再想了很久才知道怎么分治。

 

对于一个操作区间【L,R】:

如果【L,mid】区间内的添加的向量在 R 之后被删除或者不删,那么就可以用它们构建上下凸壳来更新【mid+1,R】区间内的询问。

如果【mid+1,R】区间内的删除的向量在 L 之前添加,那么也可以用它们构建上下凸壳来更新【L,mid】区间内的询问。

然后就做完了。

 

一些小技巧:下凸壳可以翻转一下变成上凸壳用同样的方法维护,nxt数组记录与操作i相关的另一个操作的位置,可以很方便的判断它是添加操作还是删除操作。

 

#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=50005;
const ll INF=0x3f3f3f3f3f3f3f3fll;
int n;
ll ans[N];
int nxt[N];
struct P
{
	int x,y;
	bool operator<(const P &t)const
	{
		return x<t.x||x==t.x&&y>t.y;
	}
	P operator-(const P &t)
	{
		return {x-t.x,y-t.y};
	}
	ll operator*(const P &t)
	{
		return 1ll*x*t.x+1ll*y*t.y;
	}
	ll operator^(const P &t)
	{
		return 1ll*x*t.y-1ll*y*t.x;
	}
}a[N];
ll cross(P a,P b,P c)
{
	return (b-a)^(c-b);
}
map<P,int>mp;
struct hull
{
	int n,top;
	P a[N],stk[N];
	void init()
	{
		n=0;
	}
	void add(P p)
	{
		a[++n]=p;
	}
	void make()
	{
		sort(a+1,a+n+1);
		top=0;
		for (int i=1;i<=n;i++)
		{
			while(top>1&&cross(stk[top-1],stk[top],a[i])>=0) top--;
			stk[++top]=a[i];
		}
	}
	ll get(P p)
	{
		if (top==0) return -INF;
		int l=1,r=top;
		while(l<r)
		{
			int mid=(l+r)/2;
			if (p*stk[mid]<p*stk[mid+1]) l=mid+1;else r=mid;
		}
		return p*stk[l];
	}
}up,down;
void solve(int l,int r)
{
	if (l==r) return;
	int mid=(l+r)/2;

	up.init(); down.init();
	for (int i=l;i<=mid;i++)
		if (nxt[i]>r)
		{
			up.add(a[i]);
			down.add({a[i].x,-a[i].y});
		}
	up.make(); down.make();
	for (int i=mid+1;i<=r;i++)
		if (nxt[i]==i)
		{
			ans[i]=max(ans[i],up.get(a[i])),
			ans[i]=max(ans[i],down.get({a[i].x,-a[i].y}));
		}

	up.init(); down.init();
	for (int i=mid+1;i<=r;i++)
		if (nxt[i]<l)
		{
			up.add(a[i]);
			down.add({a[i].x,-a[i].y});
		}
	up.make(); down.make();
	for (int i=l;i<=mid;i++)
		if (nxt[i]==i)
		{
			ans[i]=max(ans[i],up.get(a[i]));
			ans[i]=max(ans[i],down.get({a[i].x,-a[i].y}));
		}

	solve(l,mid);
	solve(mid+1,r);
}
int main()
{
	while(scanf("%d",&n),n)
	{
		mp.clear();
		for (int i=1;i<=n;i++) ans[i]=-INF;
		for (int i=1;i<=n;i++)
		{
			int tp;
			scanf("%d%d%d",&tp,&a[i].x,&a[i].y);
			if (tp==1) nxt[i]=n+1,mp[a[i]]=i;
			if (tp==-1)
			{
				int id=mp[a[i]];
				nxt[id]=i; nxt[i]=id;
				mp.erase(a[i]);
			}
			if (tp==0) nxt[i]=i;
		}
		solve(1,n);
		for (int i=1;i<=n;i++)
			if (nxt[i]==i) printf("%lld\n",ans[i]);
	}
}
Avatar_small
HDFC Balance Check N 说:
2022年11月10日 22:22

The HDFC bank is one of the biggest serving banks in India; the bank has various banking services. Where bank customers can avail both manually and through online banking. Besides banking and transferring money to different accounts. HDFC Balance Check Number Missed call The bank allows customers to easily access their balance using a variety of set methods such as Missed call, SMS, Net banking, and passbook. HDFC bank clients cannot check the account balance without visiting the bank branch. Here we check on several ways in which you can avail your balance fast.


登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter