线段树优化建树 CF786B

看到区间操作想到用线段树优化建树,建一棵外向树一棵内向树,用线段树点代表整个区间内的所有点。

大佬的图

https://www.luogu.com.cn/article/ypjofq71

从树上找节点然后连边就可以,最后跑个dijktra就完成了。

我一次就过样例了,改了几次内存就过了这题,太好了!!!

#include <bits/stdc++.h>
#define ll long long
#define int ll
#define ls p<<1
#define rs p<<1|1 
#define re register 
#define pb push_back
#define pir pair<int,int>
#define f(a,x,i) for(int i=a;i<=x;i++)
#define fr(a,x,i) for(int i=a;i>=x;i--)
#define lb(x) x&(-x); 
using namespace std;
const int N=1e6+10;
const int M=8e6+10;
const int mod=1e9+7;

int n,q,s;
int cnt;
struct sss{
	int v,w;
};

vector<sss> a[N];

struct ss{
	int l,r,id;
}t1[N<<1],t2[N<<1];

int top1,top2;


int build1(int p,int l,int r){
	if(l==r){
		return t1[l].id;
	}
	t1[p].id=p;
	int mid=(l+r)>>1;
	t1[p].l=build1(++cnt,l,mid);
	t1[p].r=build1(++cnt,mid+1,r);
	a[p].push_back({t1[p].l,0});
	a[p].push_back({t1[p].r,0});
	return p;
}

int build2(int p,int l,int r){
	if(l==r){
		return t2[l].id;
	}
	t2[p].id=p;
	int mid=(l+r)>>1;
	t2[p].l=build2(++cnt,l,mid);
	t2[p].r=build2(++cnt,mid+1,r);
	a[t2[p].l].push_back({p,0});
	a[t2[p].r].push_back({p,0});
	return p;
}

void change1(int p,int pl,int pr,int l,int r,int x,int w){
	if(pl>=l&&pr<=r){
		a[x].push_back({p,w});
		return;
	}
	int mid=(pl+pr)>>1;
	if(l<=mid) change1(t1[p].l,pl,mid,l,r,x,w);
	if(r>mid) change1(t1[p].r,mid+1,pr,l,r,x,w);
}

void change2(int p,int pl,int pr,int l,int r,int x,int w){
	if(pl>=l&&pr<=r){
		a[p].push_back({x,w});
		return;
	}
	int mid=(pl+pr)>>1;
	if(l<=mid) change2(t2[p].l,pl,mid,l,r,x,w);
	if(r>mid) change2(t2[p].r,mid+1,pr,l,r,x,w);
}
int dis[N];
int vis[N];
void dijkstra(int s){
	for(int i=1;i<=cnt;i++) dis[i]=1e18;
	dis[s]=0;
	priority_queue<pir,vector<pir>,greater<pir> > q;
	q.push({0,s});
	while(!q.empty()){
		int u=q.top().second;
		q.pop();
		if(vis[u]) continue;
		vis[u]=1;
		for(auto i:a[u]){
			int v=i.v;
			int w=i.w;
			if(dis[v]>dis[u]+w){
				dis[v]=dis[u]+w;
				q.push({dis[v],v});
			}
		}
	}
}

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(nullptr);   
	
	cin>>n>>q>>s;

	for(int i=1;i<=n;i++){
		t1[i].id=i;
		t2[i].id=i+n;
		a[i].push_back({i+n,0});
		a[i+n].push_back({i,0});
	}
	cnt=2*n;
	top1=build1(++cnt,1,n);
	top2=build2(++cnt,1,n);

	for(int i=1;i<=q;i++){
		int op,u,v,w,l,r;
		cin>>op;
		if(op==1){
			cin>>u>>v>>w;
			a[u].push_back({v,w});
		}
		else if(op==2){
			cin>>u>>l>>r>>w;
			change1(top1,1,n,l,r,u+n,w);
		}
		else{
			cin>>u>>l>>r>>w;
			change2(top2,1,n,l,r,u,w);
		}
	}

	dijkstra(s);

	for(int i=1;i<=n;i++){
		if(dis[i]==1e18) cout<<"-1 ";
		else cout<<dis[i]<<" ";
	}

    return 0;
}
posted @ 2025-02-01 15:07  sad_lin  阅读(7)  评论(0)    收藏  举报