Codeforces-786B-Legacy (线段树+最短路)

题目链接: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;
}

你可能感兴趣的:(最短路,线段树,贪心)