zoukankan      html  css  js  c++  java
  • NOIP 模拟 $15; ext{影子}$

    题解 (by;zjvarphi)

    一道并查集的题

    对于它路径上点权,我们可以转化一下:对于一个点,它在哪些路径上是最小的点权

    那么我们排个序,从大到小加入点,每回加入时,将这个点与它所相连的且权值比它大的点所在集合合并

    那么这个新集合中,这个点的权值一定是最小的,所以求出这个集合的直径即可

    对于这个新集合的直径,一定是由原来的集合的直径的端点组合而来的,或就直接是两个集合中直径大的那个

    一共六种情况,枚举即可,复杂度可以做到 (O(nlogn))

    Code
    
    
    #include<bits/stdc++.h>
    #define ri register signed
    #define p(i) ++i
    using namespace std;
    namespace IO{
        char buf[1<<21],*p1=buf,*p2=buf;
        #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++
        template<typename T>inline void read(T &x) {
            ri f=1;x=0;register char ch=gc();
            while(ch<'0'||ch>'9') {if (ch=='-') f=0;ch=gc();}
            while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=gc();}
            x=f?x:-x;
        }
    }
    using IO::read;
    namespace nanfeng{
        #define cmax(x,y) ((x)>(y)?(x):(y))
        #define cmin(x,y) ((x)>(y)?(y):(x))
        #define FI FILE *IN
        #define FO FILE *OUT
        typedef long long ll;
        static const int N=1e5+7;
        int first[N],fa[N],w[N],head[N],st[N<<1][19],lg[N<<1],dep[N],p[N],ol,n,T,t=1;
        ll dis[N],wl[N],ans;
        struct edge{int v,nxt,w;}e[N<<1];
        struct node{int x1,x2;}pnt[N];
        inline void add(int u,int v,int w) {
            e[t].v=v,e[t].w=w,e[t].nxt=first[u],first[u]=t++;
            e[t].v=u,e[t].w=w,e[t].nxt=first[v],first[v]=t++;
        }
        int find(int x) {return fa[x]==x?x:fa[x]=find(fa[x]);}
        void dfs(int x,int f) {
            head[st[p(ol)][0]=x]=ol;
            for (ri i(first[x]),v;i;i=e[i].nxt) {
                if ((v=e[i].v)==f) continue;
                dep[v]=dep[x]+1,dis[v]=dis[x]+e[i].w;
                dfs(v,x);
                st[p(ol)][0]=x;
            }
        }
        inline void init_rmq() {
            dfs(1,0);
            int k=lg[ol];
            for (ri j(1);j<=k;p(j)) {
                ri len=1<<j;
                for (ri i(1);i+len-1<=ol;p(i)) {
                    ri x1=st[i][j-1],x2=st[i+(1<<j-1)][j-1];
                    st[i][j]=dep[x1]<dep[x2]?x1:x2;
                }
            }
        }
        inline int Getlca(int u,int v) {
            if (head[u]>head[v]) swap(u,v);
            ri k=lg[head[v]-head[u]+1];
            ri x1=st[head[u]][k],x2=st[head[v]-(1<<k)+1][k];
            return dep[x1]<dep[x2]?x1:x2;
        }
        inline int cmp(int x,int y) {return w[x]>w[y];}
        inline int main() {
            // FI=freopen("nanfeng.in","r",stdin);
            // FO=freopen("nanfeng.out","w",stdout);
            for (ri i(2);i<N<<1;p(i)) lg[i]=lg[i>>1]+1;
            read(T);
            for (ri z(1);z<=T;p(z)) {
                memset(first,0,sizeof(first));
                memset(wl,0,sizeof(wl));
                t=1,ans=ol=0;
                read(n);
                for (ri i(1);i<=n;p(i)) read(w[i]),fa[i]=p[i]=i,pnt[i].x1=pnt[i].x2=i;
                for (ri i(1),u,v,ew;i<n;p(i)) read(u),read(v),read(ew),add(u,v,ew);
                init_rmq();
                sort(p+1,p+n+1,cmp);
                for (ri i(1);i<=n;p(i)) {
                    ri cur=p[i];
                    // printf("%d %d ans=%lld
    ",w[cur],cur,ans);
                    for (ri j(first[cur]),v;j;j=e[j].nxt) {
                        if (w[v=e[j].v]<w[cur]) continue;
                        ri r1=find(e[j].v),r2=find(cur);
                        ri r1x1=pnt[r1].x1,r1x2=pnt[r1].x2;
                        ri r2x1=pnt[r2].x1,r2x2=pnt[r2].x2;
                        ri l11=Getlca(r1x1,r2x1),l12=Getlca(r1x1,r2x2);
                        ri l21=Getlca(r1x2,r2x1),l22=Getlca(r1x2,r2x2);
                        ri nx1=r1x1,nx2=r1x2;
                        // if (cur==1) printf("in r2=%d nx1=%d nx2=%d %lld
    ",r2,r2x1,r2x2,wl[r2]);
                        register ll res=wl[r1];
                        
                        if (wl[r1]<wl[r2]) res=wl[r2],nx1=r2x1,nx2=r2x2;
                            
                        if (res<dis[r1x1]+dis[r2x1]-(dis[l11]<<1)) 
                            res=dis[r1x1]+dis[r2x1]-(dis[l11]<<1),nx1=r1x1,nx2=r2x1; 
                        if (res<dis[r1x1]+dis[r2x2]-(dis[l12]<<1)) 
                            res=dis[r1x1]+dis[r2x2]-(dis[l12]<<1),nx1=r1x1,nx2=r2x2;
                        if (res<dis[r1x2]+dis[r2x1]-(dis[l21]<<1)) 
                            res=dis[r1x2]+dis[r2x1]-(dis[l21]<<1),nx1=r1x2,nx2=r2x1;
                        if (res<dis[r1x2]+dis[r2x2]-(dis[l22]<<1)) 
                            res=dis[r1x2]+dis[r2x2]-(dis[l22]<<1),nx1=r1x2,nx2=r2x2;
                        // res=max(res,di[r1x1]+dis[r2x1]-(dis[Getlca(r1x1,r2x1)]<<1));
                        // res=max(res,di[r1x1]+dis[r2x2]-(dis[Getlca(r1x1,r2x2)]<<1));
                        // res=max(res,di[r1x2]+dis[r2x1]-(dis[Getlca(r1x2,r2x1)]<<1));
                        // res=max(res,di[r1x2]+dis[r2x2]-(dis[Getlca(r1x2,r2x2)]<<1));
                        wl[fa[r1]=r2]=res;
                        ans=cmax(ans,res*w[cur]);
                        pnt[r2].x1=nx1,pnt[r2].x2=nx2;
                        // if (cur==1) printf("out r2=%d nx1=%d nx2=%d %lld
    ",r2,r2x1,r2x2,wl[r2]);
                        // printf("w[%d]=%d %d %d res=%lld ans=%lld
    ",cur,w[cur],nx1,nx2,res,ans);
                    }
                    // printf("%d %d ans=%lld
    ",w[cur],cur,ans);
                }
                printf("%lld
    ",ans);
            }
            return 0;
        }  
        // #undef int
    }
    int main() {return nanfeng::main();} 
    
  • 相关阅读:
    日区 Apple ID共享
    强大的视频跨平台视频处理软件
    百度网盘无限速
    App Store看片神器,请收好
    bootstrap 中这段代码 使bundles 失败
    C# EF中调用 存储过程并调回参数
    mvc 默认访问 Area 下控制器方法
    怎样用SQL语句查看查询的性能指标
    slice 定义和用法
    C# Regex类用法
  • 原文地址:https://www.cnblogs.com/nanfeng-blog/p/15018888.html
Copyright © 2011-2022 走看看