【NOI2019】弹跳

【NOI2019】弹跳

Description

跳蚤国有 \(n\) 座城市,分别编号为 \(1 - n\)\(1\) 号城市为首都。所有城市分布在一个\(w \times h\) 范围的网格上。每座城市都有一个整数坐标 \((x, y) (1 \leq x \leq w, 1 \leq y \leq h)\),不同城市的坐标不相同。

在跳蚤国中共有 \(m\) 个弹跳装置,分别编号为 \(1 - m\),其中 \(i\) 号弹跳装置位于 \(p_i\) 号城市,并具有参数 \(t_i, L_i, R_i, D_i, U_i\)。利用该弹跳装置,跳蚤可花费 \(t_i (t_i > 0)\) 个单位时间,从 \(p_i\) 号城市跳至坐标满足 \(L_i \leq x \leq R_i, D_i \leq y \leq U_i (1 \leq L_i \leq R_i \leq w, 1 \leq D_i \leq U_i \leq h)\) 的任意一座城市。需要注意的是,一座城市中可能存在多个弹跳装置,也可能没有弹跳装置。

由于城市间距离较远,跳蚤们必须依靠弹跳装置出行。具体来说,一次出行将经过
若干座城市,依次经过的城市的编号可用序列 \(a_0, a_1, \cdots , a_k\) 表示;在此次出行中,依次利用的弹跳装置的编号可用序列 \(b_1, b_2, \cdots , b_k\) 表示。其中每座城市可在序列 \(\{a_j\}\) 中出现任意次,每个弹跳装置也可在序列 \(\{b_j\}\) 中出现任意次,且满足,对于每个 \(j (1 \leq j \leq k)\),编号为 \(b_j\) 的弹跳装置位于城市 \(a_{j-1}\),且跳蚤能通过该弹跳装置跳至城市 \(a_j\)。我们称这是一次从城市 \(a_0\) 到城市 \(a_k\) 的出行,其进行了 \(k\) 次弹跳,共花费 \(\sum^k_{i=1} t_{b_{i}}\) 个单位时间。

现在跳蚤国王想知道,对于跳蚤国除首都(\(1\) 号城市)外的每座城市,从首都出发,到达该城市最少需要花费的单位时间。跳蚤国王保证,对每座城市,均存在从首都到它的出行方案。

Input

第一行包含四个整数 \(n, m,w, h\),变量的具体意义见题目描述。

接下来 \(n\) 行,第 \(i\) 行包含两个整数 \(x_i, y_i\),表示 \(i\) 号城市的坐标。

接下来 \(m\) 行,第 \(i\) 行包含六个整数 \(p_i, t_i, L_i, R_i, D_i, U_i\),分别表示 \(i\) 号弹跳装置所在的城市编号、弹跳所需的时间、可到达的矩形范围。这些整数的具体意义见题目描述。

Output

输出 \(n - 1\) 行,第 \(i\) 行包含一个整数,表示从跳蚤国首都到 \(i + 1\) 号城市最少需要花费的单位时间。

Sample Input

5 3 5 5
1 1
3 1
4 1
2 2
3 3
1 123 1 5 1 5
1 50 1 5 1 1
3 10 2 2 2 2

Sample Output

50
50
60
123

Data Constraint

\(1 \leq n \leq 70000 , 1 \leq m \leq 150000 , 1 \leq w, h \leq n , 1 \leq t_i \leq 10000\)

Solution

来做做典题

一个简单的想法是线段树优化建图,但是这题卡空间,

而且这个做法常数巨大,树套树肯定是冲不过去的

观察一下

这题的边权只跟起点有关

所以如果把矩阵看做点的话,原图每个点只会入队一次,删除一次

所以使用线段树套set,每次暴力遍历更新信息

然而被KDT暴打(

Code

#include<bits/stdc++.h>
using namespace std;
#define F(i,a,b) for(int i=a;i<=b;i++)
#define Fd(i,a,b) for(int i=a;i>=b;i--)
#define LL long long
#define N 70010
#define M 150010
#define ls x<<1
#define rs (x<<1)|1

LL dis[N];
int n,m,W,H,vis[M];
struct node{
	int id,x,y;
	node(int _id=0,int _x=0,int _y=0){id=_id;x=_x;y=_y;}
	bool operator<(node A)const{return y<A.y||y==A.y&&id<A.id;}
}a[N];
struct mode{
	int ti,L,R,D,U;
}b[M];
vector<int>e[N];
struct point{
	int x;LL y;
	point(int _x=0,LL _y=0){x=_x;y=_y;}
	bool operator<(const point&A)const{return y>A.y;}
};
priority_queue<point>q;
struct tree{
	set<node>s[N*4];
	void modify(int x,int l,int r,int v,int k){
		if(k)s[x].insert(a[v]);
		else s[x].erase(a[v]);
		if(l==r)return;
		int mid=l+r>>1;
		a[v].x<=mid?modify(ls,l,mid,v,k):modify(rs,mid+1,r,v,k);
	}
	void change(int x,int l,int r,int pos,LL v){
		if(r<b[pos].L||l>b[pos].R)return;
		if(l>=b[pos].L&&r<=b[pos].R){
			auto it=s[x].lower_bound(node(0,0,b[pos].D));
			queue<int>p;
			int cnm=s[x].size();
			for(;it!=s[x].end();it++){
				node u=*it;
				if(u.y>b[pos].U)break;
				dis[u.id]=v;
				p.push(u.id);
				for(auto d:e[u.id])q.push(point(d,v+b[d].ti));
			}
			while(!p.empty())modify(1,1,W,p.front(),0),p.pop();
			return;
		}
		int mid=l+r>>1;
		change(ls,l,mid,pos,v);change(rs,mid+1,r,pos,v);
	}
}t;

int main(){
	scanf("%d%d%d%d",&n,&m,&W,&H);
	F(i,1,n){
		int x,y;
		scanf("%d%d",&x,&y);
		a[i]=node(i,x,y);
		t.modify(1,1,W,i,1);
	}
	F(i,1,m){
		int p,t,l,r,d,u;
		scanf("%d%d%d%d%d%d",&p,&t,&l,&r,&d,&u);
		b[i]=(mode){t,l,r,d,u};
		e[p].push_back(i);
	}
	b[0]=(mode){0,a[1].x,a[1].x,a[1].y,a[1].y};
	q.push(point(0,0));
	while(!q.empty()){
		point u=q.top();q.pop();
		if(vis[u.x])continue;
		vis[u.x]=1;
		t.change(1,1,W,u.x,u.y);
	}
	F(i,2,n)printf("%lld\n",dis[i]);
	return 0;
}
posted @ 2023-03-06 20:07  冰雾  阅读(24)  评论(0编辑  收藏  举报