题解CF786B【レガシー】

この問題は、3つの動作モードをサポートするために私たちを必要とします。

偶数点①点のエッジまで。②もポイント範囲に側。③エッジ点に接続されたセクション。

そして、最短の答えを実行します。

最適化された建設セグメントツリー図を使用することを検討してください。

2本のセグメントの木、木及び木、コレクションの範囲の元のノードの各ノードを内蔵。木と木のリーフノードが原点なので、リーフノードに対応する2つのツリーが無向接続されているとしても、側にいた父親に息子のように木の内部に、彼の父のツリー内であっても、側にいました側、これらは右のコラージュです\(0 \)

以下の図、木、木の右側の左側に。

動作は一時的に、子ノードから葉は葉の縁部(赤線)に接続されています。

第2の動作、エッジ部(青線)に接続されたノードに対応するツリーノードからの葉。

リーフに接続されたエッジ(緑の線)に対応するツリーノードゾーンから操作3、。

具体的な実装の詳細は、コードを確認してください。

開くことを忘れないでください(長い\長い\)\をし、大規模な配列を開きます。

\(コード:\)

#include<bits/stdc++.h>
#define maxn 800010
#define inf 2000000000
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int n,m,s,flag;
struct edge
{
    int to,nxt,v;
}e[maxn];
int head[maxn],edge_cnt;
void add(int from,int to,int val)
{
    e[++edge_cnt]=(edge){to,head[from],val};
    head[from]=edge_cnt;
}
int in_root,out_root,tree_cnt;
int ls[maxn],rs[maxn],in_num[maxn],out_num[maxn];
void build_in(int L,int R,int &cur)
{
    cur=++tree_cnt;
    if(L==R)
    {
        in_num[L]=cur;
        return;
    }
    int mid=(L+R)>>1;
    build_in(L,mid,ls[cur]);
    build_in(mid+1,R,rs[cur]);
    add(ls[cur],cur,0),add(rs[cur],cur,0);
}
void build_out(int L,int R,int &cur)
{
    cur=++tree_cnt;
    if(L==R)
    {
        out_num[L]=cur;
        return;
    }
    int mid=(L+R)>>1;
    build_out(L,mid,ls[cur]);
    build_out(mid+1,R,rs[cur]);
    add(cur,ls[cur],0),add(cur,rs[cur],0);
}
void modify_in(int L,int R,int l,int r,int pos,int val,int &cur)
{
    if(L<=l&&R>=r)
    {
        add(cur,pos,val);
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) modify_in(L,R,l,mid,pos,val,ls[cur]);
    if(R>mid) modify_in(L,R,mid+1,r,pos,val,rs[cur]);
}
void modify_out(int L,int R,int l,int r,int pos,int val,int &cur)
{
    if(L<=l&&R>=r)
    {
        add(pos,cur,val);
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid) modify_out(L,R,l,mid,pos,val,ls[cur]);
    if(R>mid) modify_out(L,R,mid+1,r,pos,val,rs[cur]);
}
ll dis[maxn];
bool vis[maxn];
struct node
{
    ll val;
    int num;
};  
bool operator <(const node &x,const node &y)
{
    return x.val>y.val;
}
priority_queue<node> q;
void dijkstra()
{
    s=in_num[s];
    for(int i=1;i<=tree_cnt;++i) dis[i]=inf;
    dis[s]=0;
    q.push((node){0,s});
    while(!q.empty())
    {
        node tmp=q.top();
        q.pop();
        int x=tmp.num;
        if(vis[x]) continue;
        vis[x]=true;
        for(int i=head[x];i;i=e[i].nxt)
        {
            int y=e[i].to,v=e[i].v;
            if(dis[y]>dis[x]+v)
            {
                dis[y]=dis[x]+v;
                q.push((node){dis[y],y});
            }
        }
    }
}
int main()
{
    read(n),read(m),read(s);
    build_in(1,n,in_root);
    build_out(1,n,out_root);
    for(int i=1;i<=n;++i)
        add(in_num[i],out_num[i],0),add(out_num[i],in_num[i],0);
    while(m--)
    {
        read(flag);
        int x,y,l,r,v;
        if(flag==1)
        {
            read(x),read(y),read(v);
            add(in_num[x],out_num[y],v);
        }
        if(flag==2)
        {
            read(x),read(l),read(r),read(v);
            modify_out(l,r,1,n,in_num[x],v,out_root);
        }
        if(flag==3)
        {
            read(x),read(l),read(r),read(v);
            modify_in(l,r,1,n,out_num[x],v,in_root);
        }
    }
    dijkstra();
    for(int i=1;i<=n;++i)
    {
        if(dis[out_num[i]]==inf) printf("-1 ");
        else printf("%lld ",dis[out_num[i]]);
    }
    return 0;
}

おすすめ

転載: www.cnblogs.com/lhm-/p/12229830.html