习题:Legacy(线段树优化建图)
题目
思路
类似于建虚点
注意到题目中的操作区间都是连续的,用线段树来优化建图即可
代码
#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
struct node_tre
{
int l;
int r;
}tre[2][400005];//0表示出,1表示入
struct node_g
{
int e;
long long w;
friend bool operator < (const node_g &a,const node_g &b)
{
return a.w>b.w;
}
};
int n,m,s;
int opt;
int u,l,r,w;
bool vis[900015];
long long dis[900005];
vector<node_g> g[900015];
priority_queue<node_g> q;
void build(int l,int r,int k)
{
tre[0][k].l=tre[1][k].l=l;
tre[0][k].r=tre[1][k].r=r;
if(l==r)
{
g[l].push_back((node_g){n+k,0});
g[5*n+k].push_back((node_g){l,0});
return;
}
g[n+(k<<1)].push_back((node_g){n+k,0});
g[n+(k<<1|1)].push_back((node_g){n+k,0});
g[5*n+k].push_back((node_g){5*n+(k<<1),0});
g[5*n+k].push_back((node_g){5*n+(k<<1|1),0});
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
void change(int l,int r,int st,long long w,int opt,int k)
{
if(l>tre[opt][k].r||tre[opt][k].l>r)
return;
if(l<=tre[opt][k].l&&tre[opt][k].r<=r)
{
if(opt==0)
g[st].push_back((node_g){5*n+k,w});
else
g[n+k].push_back((node_g){st,w});
return;
}
change(l,r,st,w,opt,k<<1);
change(l,r,st,w,opt,k<<1|1);
}
void dij(int s)
{
memset(dis,0x3f,sizeof(dis));
q.push((node_g){s,0});
dis[s]=0;
while(!q.empty())
{
node_g u=q.top();
q.pop();
if(vis[u.e])
continue;
vis[u.e]=1;
for(int i=0;i<g[u.e].size();i++)
{
int v=g[u.e][i].e;
long long w=g[u.e][i].w;
if(w+dis[u.e]<dis[v])
{
dis[v]=w+dis[u.e];
q.push((node_g){v,dis[v]});
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>m>>s;
build(1,n,1);
for(int i=1;i<=m;i++)
{
cin>>opt;
if(opt==1)
{
cin>>l>>r>>w;
if(l==r)
continue;
g[l].push_back((node_g){r,w});
}
else
{
opt-=2;
cin>>u>>l>>r>>w;
change(l,r,u,w,opt,1);
}
}
dij(s);
for(int i=1;i<=n;i++)
{
if(dis[i]==dis[0])
cout<<"-1\n";
else
cout<<dis[i]<<'\n';
}
return 0;
}

浙公网安备 33010602011771号