Codeforces-786B-Legacy (線段樹+最短路)
阿新 • • 發佈:2018-12-24
看到區間很容易就能想到線段樹。
對於操作2,我們可以建立一棵線段樹,線段樹的某一個結點表示區間
當得到一個操作
每一次新建邊的操作複雜度是
對於操作3,與操作2類似。
#include<bits/stdc++.h>
using namespace std ;
typedef long long ll;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int maxn=1e5+7;
struct Node
{
int v;
ll d;
Node(){}
Node(int _v,ll _d):v(_v),d(_d){}
bool operator < (const Node & r) const
{
return d>r.d;
}
};
int n,q,s;
int p_2[maxn<<2],p_3[maxn<<2 ];
vector<Node> adj[maxn<<3|1];
bool vis[maxn<<3|1];
ll d[maxn<<3|1];
void build_2(int rt, int l, int r)
{
p_2[rt]=++n;
for(int i=l;i<=r;i++)
adj[p_2[rt]].push_back(Node(i,0));
if(l==r) return ;
int mid=(l+r)>>1;
build_2(rt<<1,l,mid);
build_2(rt<<1 |1,mid+1,r);
}
void build_3(int rt,int l,int r)
{
p_3[rt]=++n;
for(int i=l;i<=r;i++)
adj[i].push_back(Node(p_3[rt],0));
if(l==r) return ;
int mid=(l+r)>>1;
build_3(rt<<1,l,mid);
build_3(rt<<1|1,mid+1,r);
}
void update_2(int rt,int l,int r,int ql,int qr,int id,ll w)
{
if(l>=ql&&r<=qr)
{
adj[id].push_back(Node(p_2[rt],w));
return ;
}
int mid=(l+r)>>1;
if(ql<=mid) update_2(rt<<1,l,mid,ql,qr,id,w);
if(qr>mid) update_2(rt<<1|1,mid+1,r,ql,qr,id,w);
}
void update_3(int rt,int l,int r,int ql,int qr,int id,ll w)
{
if(l>=ql&&r<=qr)
{
adj[p_3[rt]].push_back(Node(id,w));
return ;
}
int mid=(l+r)>>1;
if(ql<=mid) update_3(rt<<1,l,mid,ql,qr,id,w);
if(qr>mid) update_3(rt<<1|1,mid+1,r,ql,qr,id,w);
}
int main()
{
scanf("%d%d%d",&n,&q,&s);
int on=n;
build_2(1,1,on);
build_3(1,1,on);
int op,l,r,u,v,w;
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d",&v,&u,&w);
adj[v].push_back(Node(u,w));
}
else
{
scanf("%d%d%d%d",&v,&l,&r,&w);
if(op==2)
update_2(1,1,on,l,r,v,w);
else
update_3(1,1,on,l,r,v,w);
}
}
memset(d,0x3f,sizeof(d));
d[s]=0;
priority_queue<Node> q;
q.push(Node(s,0));
while(!q.empty())
{
Node t=q.top();q.pop();
if(vis[t.v]) continue;
vis[t.v]=true;
for(int i=0;i<adj[t.v].size();i++)
{
Node &tt=adj[t.v][i];
if(!vis[tt.v]&&d[t.v]+tt.d<d[tt.v])
{
d[tt.v]=d[t.v]+tt.d;
q.push(Node(tt.v,d[tt.v]));
}
}
}
for(int i=1;i<=on;i++)
printf("%I64d ",d[i]==INF?-1:d[i]);
return 0;
}