[ABC266Ex] Snuke Panic (2D)

Problem Statement

Takahashi is trying to catch many Snuke.

There are some pits in a two-dimensional coordinate plane, connected to Snuke's nest.

Now, $N$ Snuke will appear from the pits. It is known that the $i$-th Snuke will appear from the pit at coordinates $(X_i,Y_i)$ at time $T_i$, and its size is $A_i$.

Takahashi is at coordinates $(0,0)$ at time $0$ and can do the following two kinds of moves.

  • Move at a speed of at most $1$ in the $x$-direction (positive or negative).
  • Move at a speed of at most $1$ in the positive $y$-direction.

Moving in the negative $y$-direction is not allowed.

He can catch a Snuke appearing from a pit if and only if he is at the coordinates of that pit exactly when it appears.
The time it takes to catch a Snuke is negligible.

Find the maximum sum of the sizes of Snuke that Takahashi can catch by moving optimally.

Constraints

  • $1 \leq N \leq 10^5$
  • $1 \leq T_i \leq 10^9$
  • $0 \leq X_i,Y_i \leq 10^9$
  • $1 \leq A_i \leq 10^9$
  • The triples $(T_i,X_i,Y_i)$ are distinct.
  • All values in input are integers.

Input

Input is given from Standard Input in the following format:

$N$
$T_1$ $X_1$ $Y_1$ $A_1$
$T_2$ $X_2$ $Y_2$ $A_2$
$\vdots$
$T_N$ $X_N$ $Y_N$ $A_N$

Output

Print the answer as an integer.


Sample Input 1

3
1 0 0 100
3 2 1 10
5 3 1 1

Sample Output 1

101

The optimal strategy is as follows.

  • Wait at coordinates $(0,0)$ to catch the first Snuke at time $1$.
  • Go to coordinates $(3,1)$ to catch the third Snuke at time $5$.

It is impossible to catch both the first and second Snuke, so this is the best he can.


Sample Input 2

2
100 0 1 1
200 1 0 10

Sample Output 2

10

Moving in the negative $y$-direction is not allowed, so he cannot catch the first Snuke and then the second.


Sample Input 3

10
797829355 595605750 185676190 353195922
913575467 388876063 395940406 533206504
810900084 201398242 159760440 87027328
889089200 220046203 85488350 325976483
277429832 161055688 73308100 940778720
927999455 429014248 477195779 174616807
673419335 415891345 81019893 286986530
989248231 147792453 417536200 219371588
909664305 22150727 414107912 317441890
988670052 140275628 468278658 67181740

考虑 dp,定义 \(dp_{i}\) 为到达点 \(i\) 时的最大得分。明显 dp 无环。
满足以下条件时,\(dp_i\) 可以从 \(dp_j\) 转移.

  1. \(t_j<t_i\)
  2. \(y_j<y_i\)
  3. \(|x_i-x_j|+y_i-y_j\le t_i-t_j\)(路程差要小于时间差)

然后会发现,若条件 3 满足,条件 1 也满足。

然后把条件 3 的绝对值拆开,移项。

  1. \(y_j<y_i\)
  2. \(t_j-x_j-y_j\le t_i-x_i-y_i\)
  3. \(t_j+x_j-y_j\le t_i+x_i-y_i\)

那么就是一个三维偏序问题。把所有点按 \(y\) 排序,然后第二维第三维用一个树状数组套线段树维护就行了。注意将从 \(0\) 都到不了的点清掉。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
typedef long long LL;
int n,x,y,t,aaa,lshc[N],lshb[N],rt[N],lc[N*200],rc[N*200],idx;
LL k,ans,tr[N*200];
struct node{
	int a,b,c,d;
	bool operator<(const node&n)const{
		if(a!=n.a)
			return a<n.a;
		if(b!=n.b)
			return b<n.b;
		return c<n.c;
	}
}a[N];
void xiugai(int&o,int l,int r,int x,LL z)
{
	if(!o)
		o=++idx;
	if(l==r)
	{
		tr[o]=max(tr[o],z);
		return;
	}
	int md=l+r>>1;
	if(md>=x)
		xiugai(lc[o],l,md,x,z);
	else
		xiugai(rc[o],md+1,r,x,z);
	tr[o]=max(tr[lc[o]],tr[rc[o]]);
}
LL query(int o,int l,int r,int x,int y)
{
	if(!o)
		return 0;
	if(x<=l&&r<=y)
		return tr[o];
	int md=l+r>>1;
	LL ans=0;
	if(md>=x)
		ans=max(ans,query(lc[o],l,md,x,y));
	if(md<y)
		ans=max(ans,query(rc[o],md+1,r,x,y));
	return ans;
}
void update(int x,int y,LL z)
{
	for(;x<=n;x+=x&-x)
		xiugai(rt[x],1,n,y,z);
}
LL ask(int x,int y)
{
	LL ans=0;
	for(;x;x-=x&-x)
		ans=max(ans,query(rt[x],1,n,1,y));
	return ans;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d%d%d",&t,&x,&y,&aaa);
		if(t-x-y<0||x+t-y<0)
		{
			--i,--n;
			continue;
		}
		a[i]=(node){y,t-x-y,x+t-y,aaa};
		lshb[i]=t-x-y;
		lshc[i]=x+t-y;
	}
	for(int i=1;i<=n;i++)
		rt[i]=++idx;
	sort(a+1,a+n+1);
	sort(lshb+1,lshb+n+1);
	sort(lshc+1,lshc+n+1);
	for(int i=1;i<=n;i++)
	{
//		printf("%d\n",i);
		a[i].b=lower_bound(lshb+1,lshb+n+1,a[i].b)-lshb;
		a[i].c=lower_bound(lshc+1,lshc+n+1,a[i].c)-lshc;
	}
	for(int i=1;i<=n;i++)
	{
//		puts("hjhyyds");
//		printf("%d %d %d\n",a[i].b,a[i].c,a[i].d);
		k=ask(a[i].b,a[i].c)+a[i].d;
		update(a[i].b,a[i].c,k);
		ans=max(ans,k);
	}
	printf("%lld",ans);
}
posted @ 2022-12-21 21:32  灰鲭鲨  阅读(20)  评论(0编辑  收藏  举报