zoukankan      html  css  js  c++  java
  • 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();}
    
  • 相关阅读:
    MSSQL ADO.NET
    MSSQL 详解SQL Server连接(内连接、外连接、交叉连接)
    MSSQL DBOtherSQL
    java8时间转换成字符串
    泛型
    给定一个排序数组,你需要在 原地 删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。
    利用栈判断有效的括号
    回文数
    service层对 @NotBlank注解起作用
    集合的使用
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15538264.html
Copyright © 2011-2022 走看看