题目链接:Codeforces-786B-Legacy
看到区间很容易就能想到线段树。
对于操作2,我们可以建立一棵线段树,线段树的某一个结点表示区间 [l,r] ,那么在图中建立一个结点 u 表示区间 [l,r] ,新建点 u 指向 l,l+1,l+2...r 的边,权值为 0 。
当得到一个操作 (v,l,r,w) 时,查询一次线段树,把所有符合 [ql,qr]∈[l,r] 的极大区间结点建立一条被 v 指向的边,权值为 w 。这样就能表示 v 指向 [l,r] 了。
每一次新建边的操作复杂度是 O(2logn) ,
对于操作3,与操作2类似。
#include
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 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 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;iif(!vis[tt.v]&&d[t.v]+tt.dfor(int i=1;i<=on;i++)
printf("%I64d ",d[i]==INF?-1:d[i]);
return 0;
}