cunzai_zsy0531

关注我

P5471 [NOI2019]弹跳 题解

题面

这个题是二维的情况,一个点向一个矩形连边。一维的时候就是线段树优化建图,这里只能树套树优化建图了。但是这道题空间只有128MB,显然空间不能达到 \(O(n\log^2 n)\) 级别,所以考虑线段树套平衡树 (set) 来解决。

一个通常用来解决这种问题的方案是,不直接连边,而是把每个矩形在跑最短路的时候看做一个点,每从堆中取出一个 dist 最小的矩形,就把这个矩形中的所有点更新并且删除。由于这样树套树的空间复杂度是 \(O(n\log n)\),每个点只会被删除一次,所以总的复杂度是 \(O(n\log^2 n+m)\),可以通过本题。

注意事项:set 里若想存结构体类型的信息,需要重定义 \(<\) 号,并且要注意 lower_bound 时关键字信息相等的情况。it 可以现用现定义,不然容易重复定义!

点击查看代码
#include<iostream>
#include<cstdio>
#include<set>
#include<queue>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N=70000+13,M=150000+13;
struct node{
	int id,x,y;
	bool operator <(node a)const{return y==a.y?id<a.id:y<a.y;}
}s[N];
struct Node{int p,w,lx,rx,ly,ry;}a[M];
int n,m,W,H;
vector<int> g[N];
#define pb push_back
struct SegTree{int l,r;set<node> pos;}t[N<<2];
set<node>::iterator it;
#define ls p<<1
#define rs p<<1|1
#define mid ((t[p].l+t[p].r)>>1)
void build(int p,int l,int r){
	t[p].l=l,t[p].r=r,t[p].pos.clear();
	if(l==r) return;
	build(ls,l,mid),build(rs,mid+1,r);
}
void Insert(int p,int id){
	t[p].pos.insert(s[id]);
	if(t[p].l==t[p].r) return;
	Insert(s[id].x<=mid?ls:rs,id);
}
void Erase(int p,int id){
	t[p].pos.erase(s[id]);
	if(t[p].l==t[p].r) return;
	Erase(s[id].x<=mid?ls:rs,id);
}
typedef pair<int,int> pii;
#define mp make_pair
#define fi first
#define se second
priority_queue<pii,vector<pii>,greater<pii> > q;
int dist[N];
bool vis[M];
queue<int> Q;
void work(int p,int id,int v){
	int l=a[id].lx,r=a[id].rx;
	if(l<=t[p].l&&t[p].r<=r){
		it=t[p].pos.lower_bound((node){0,0,a[id].ly});
		for(;it!=t[p].pos.end()&&(it->y)<=a[id].ry;++it){
			if(dist[it->id]>v){
				dist[it->id]=v,Q.push(it->id);
				for(vector<int>::iterator It=g[it->id].begin();It!=g[it->id].end();++It)
					q.push(mp(v+a[*It].w,*It));
			}
		}
		while(!Q.empty()) Erase(1,Q.front()),Q.pop();
		return;
	}
	if(l<=mid) work(ls,id,v);
	if(r>mid) work(rs,id,v);
}
inline void dijk(){
	memset(dist,0x3f,sizeof dist);
	memset(vis,0,sizeof vis);
	q.push(mp(0,0));
	while(!q.empty()){
		int u=q.top().se,d=q.top().fi;q.pop();
		if(vis[u]) continue;vis[u]=1;
		work(1,u,d);
	}
	for(int i=2;i<=n;++i) printf("%d\n",dist[i]);
}
int main(){
	scanf("%d%d%d%d",&n,&m,&W,&H);
	build(1,1,W);
	for(int i=1,x,y;i<=n;++i){
		scanf("%d%d",&s[i].x,&s[i].y);s[i].id=i;
		Insert(1,i);
	}
	a[0].lx=a[0].rx=s[1].x,a[0].ly=a[0].ry=s[1].y;
	for(int i=1;i<=m;++i){
		scanf("%d%d%d%d%d%d",&a[i].p,&a[i].w,&a[i].lx,&a[i].rx,&a[i].ly,&a[i].ry);
		g[a[i].p].pb(i);
	}
	dijk();
	return 0;
}
posted @ 2022-05-20 11:53  cunzai_zsy0531  阅读(41)  评论(0编辑  收藏  举报