• NOIP 模拟 $94; m 欢乐豆$


    题解 (by;zjvarphi)

    (x ightarrow y) 边权值的修改转换成 (x,y) 之间连了一条无向边。

    先求出来在联通块中点对之间到达的最短距离,而联通块内的点到联通块外的点一定是先走到联通块边界再走到外界。

    这就是求 (min dis_v+a_v)

    使用 (dijkstra) 算法,发现更新最短路的时候有大部分边权值都是一样的,这样直接在线段树上模拟即可。

    具体看代码。

    Code
    #include<bits/stdc++.h>
    #define ri signed
    #define pd(i) ++i
    #define bq(i) --i
    #define func(x) std::function<x>
    namespace IO{
        char buf[1<<21],*p1,*p2;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?(-1):*p1++
        #define dg1(x) std::cerr << #x"=" << x << ' '
        #define dg2(x) std::cerr << #x"=" << x << std::endl
        #define Dg(x) assert(x)
        struct nanfeng_stream{
            template<typename T>inline nanfeng_stream &operator>>(T &x) {
                bool f=false;x=0;char ch=gc();
                while(!isdigit(ch)) f|=ch=='-',ch=gc();
                while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=gc();
                return x=f?-x:x,*this;
            }
        }cin;
    }
    using IO::cin;
    namespace nanfeng{
        #define int long long
        #define pb emplace_back
        #define FI FILE *IN
        #define FO FILE *OUT
        template<typename T>inline T cmax(T x,T y) {return x>y?x:y;}
        template<typename T>inline T cmin(T x,T y) {return x>y?y:x;}
        using ll=long long;
        static const int N=1e5+7,M=3e3+7;
        static const ll INF=1e18;
        struct TO{int v,w;};
        int a[N],fa[N],siz[N],id[N],nwi[N],cnt,n,m;
        ll dis[N],ans;
        std::vector<TO> G[N];
        std::vector<int> vc[N];
        std::multiset<int> st;
        func(int(int)) find=[](int x) {return x==fa[x]?x:fa[x]=find(fa[x]);};
        struct Seg{
            #define ls(x) (x<<1)
            #define rs(x) (x<<1|1)
            struct segmenttree{int x;ll ds,lz;bool tg;}T[M<<2];
            func(void(int)) up=[&](int x) {
                T[x].ds=cmin(T[ls(x)].ds,T[rs(x)].ds);
                if (T[x].ds==T[ls(x)].ds&&!T[ls(x)].tg) T[x].x=T[ls(x)].x;
                else T[x].x=T[rs(x)].x;
                T[x].tg=T[ls(x)].tg&T[rs(x)].tg;
            };
            func(void(int)) down=[&](int x) {
                if (T[x].lz==INF) return;
                if (!T[ls(x)].tg) {
                    T[ls(x)].ds=cmin(T[ls(x)].ds,T[x].lz);
                    T[ls(x)].lz=cmin(T[ls(x)].lz,T[x].lz);
                }
                if (!T[rs(x)].tg) {
                    T[rs(x)].ds=cmin(T[rs(x)].ds,T[x].lz);
                    T[rs(x)].lz=cmin(T[rs(x)].lz,T[x].lz);
                }
                T[x].lz=INF;
            };
            func(void(int,int,int)) build=[&](int x,int l,int r) {
                T[x].lz=INF,T[x].tg=false;
                if (l==r) return T[x].ds=INF,T[x].x=l,void();
                int mid=(l+r)>>1;
                build(ls(x),l,mid);
                build(rs(x),mid+1,r);
                up(x);
            };
            func(void(int,ll,int,int,int,int)) update=[&](int x,ll k,int l,int r,int lt,int rt) {
                if (T[x].tg) return;
                if (l<=lt&&rt<=r)
                    return T[x].ds=cmin(T[x].ds,k),T[x].lz=cmin(T[x].lz,k),void();
                int mid=(lt+rt)>>1;
                down(x);
                if (l<=mid) update(ls(x),k,l,r,lt,mid);
                if (r>mid) update(rs(x),k,l,r,mid+1,rt);
                up(x);
            };
            func(void(int,int,int,int)) cover=[&](int x,int p,int l,int r) {
                if (l==r) return T[x].ds=INF,T[x].tg=true,void();
                int mid=(l+r)>>1;
                down(x);
                if (p<=mid) cover(ls(x),p,l,mid);
                else cover(rs(x),p,mid+1,r);
                up(x);
            };
        }T;
        inline int main() {
            FI=freopen("happybean.in","r",stdin);
            FO=freopen("happybean.out","w",stdout);
            cin >> n >> m;
            for (ri i(1);i<=n;pd(i)) cin >> a[fa[i]=i],st.insert(a[i]),siz[i]=1;
            for (ri i(1),u,v,w;i<=m;pd(i)) {
                cin >> u >> v >> w;
                G[u].pb((TO){v,w});
                u=find(u),v=find(v);
                if (u!=v) fa[v]=u,siz[u]+=siz[v];
            }
            for (ri i(1);i<=n;pd(i)) 
                std::sort(G[i].begin(),G[i].end(),[](const TO &g1,const TO &g2) {return g1.v<g2.v;});
            for (ri i(1);i<=n;pd(i)) if (find(i)==i&&siz[i]>1) id[i]=++cnt;
            for (ri i(1);i<=n;pd(i))
                if (siz[find(i)]>1) vc[id[find(i)]].pb(i);
                else ans+=1ll*a[i]*(n-1);
            for (ri i(1);i<=cnt;pd(i)) {
                const int s=vc[i].size();
                for (ri j(0);j<s;pd(j)) {
                    const int nw=vc[i][j];
                    nwi[nw]=j+1,st.erase(st.find(a[nw]));
                }
                ll tmp=st.size()?*st.begin():INF;
                for (auto u:vc[i]) {
                    st.insert(a[u]);
                    T.build(1,1,s);
                    T.update(1,0,nwi[u],nwi[u],1,s);
                    while(!T.T[1].tg&&T.T[1].ds!=INF) {
                        int x=T.T[1].x;
                        dis[x]=T.T[1].ds;
                        ll nd=dis[x];
                        T.cover(1,x,1,s);
                        x=vc[i][x-1];
                        int lst=1;
                        for (auto v:G[x]) {
                            const int nv=nwi[v.v];
                            if (lst<=nv-1) T.update(1,nd+a[x],lst,nv-1,1,s);
                            T.update(1,nd+v.w,nv,nv,1,s);
                            lst=nv+1;
                        }
                        if (lst<=s) T.update(1,nd+a[x],lst,s,1,s);
                    }
                    ll pa=ans;
                    for (ri j(1);j<=s;pd(j)) ans+=cmin(dis[j],a[u]+tmp);
                    ll tpm=INF;
                    for (ri j(1);j<=s;pd(j)) tpm=cmin(tpm,(dis[j]+a[vc[i][j-1]])*(n-s));
                    ans+=tpm;
                }
            }
            printf("%lld
    ",ans);
            return 0;
        }
        #undef int
    }
    int main() {return nanfeng::main();}
    
  • 相关阅读:
    请用正则实现String.trim()
    事件委托的原理是什么?有什么作用?
    请简述get请求和post请求的区别
    用原生js实现,点击一个列表时,输出对应的索引
    请用js写一个函数,实现获取浏览器url中查询字符串中的参数并返回一个数组
    请描述一下cookies、sessionStorage、localStorage、session四者的区别?
    清除浮动的几种方式,各自的优缺点?
    如何使用离线存储(localStorage)?
    使用css怎么让谷歌支持小于12px的文字比如10px
    ajax有哪些方法可以实现跨域?他们都有哪些局限性?
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15538264.html
Copyright © 2020-2023  润新知