1 条题解

  • 0
    @ 2017-10-13 10:39:58

    这题其实很简单的,只是把几个模板套在了一起而已.首先可以分析危险系数最边最小路径一定在最小生成树上,然后这题实际上就转化为了一个树链问题,用一个简单的树链剖分和线段树维护就可以搞了.

    #include<bits/stdc++.h>
    #define LL long long
    const int maxn=1e6;
    const LL mod=1e9+7;
    inline const void read(LL &a)
    {
        char c=getchar();LL b=1;a=0;
        while(c<'0'||c>'9'){if(c=='-')b=-1;c=getchar();}
        while(c>='0'&&c<='9')
        {
            a=(a<<1)+(a<<3)+c-'0';
            c=getchar();
        }
        a*=b;
    }
    inline const void write(LL a)
    {
        if(a<0){putchar('-');a=-a;}
        if(a>9)write(a/10);
        putchar(a%10+'0');
    }
    inline const LL min(LL a,LL b)
    {
        if(a<b)return a;
        return b;
    }
    inline const LL max(LL a,LL b)
    {
        if(a>b)return a;
        return b;
    }
    LL n,m,t,d=0;
    LL from[maxn],to[maxn],next[maxn],point[maxn];
    inline const void add(LL a,LL b)
    {
        next[++d]=point[a];
        to[d]=b;
        point[a]=d;
    }
    struct side
    {
        LL from,to,next,height;
    }s[maxn];
    inline const bool comp(const side&a,const side&b)
    {
        if(a.height<b.height)return true;
        return false;
    }
    struct LEAST_TREE
    {
        LL belong[maxn];
        inline const LL check(LL a)
        {
            if(a==belong[a])return a;
            return belong[a]=check(belong[a]);
        }
        void solve()
        {
            for(LL i=1;i<=n;i++)belong[i]=i;
            memset(point,false,sizeof(point));
            for(LL i=1;i<=m;i++){read(s[i].from);read(s[i].to);read(s[i].height);}
            std::sort(s+1,s+1+m,comp);
            LL k=n-1,t=1;
            while(k)
            {
                if(check(s[t].from)==check(s[t].to)){t++;continue;}
                belong[check(s[t].from)]=s[t].to;
                add(s[t].from,s[t].to);
                add(s[t].to,s[t].from);
                k--;t++;
            }
        }
    }least_tree;
    LL father[maxn],top[maxn],deep[maxn];
    LL leaf[maxn],order=0,pos[maxn],init[maxn];
    struct LINK_CUT_TREE
    {
        LL son[maxn],num[maxn];
        bool vis[maxn];
        inline const void dfs1(LL p)
        {
            vis[p]=true;
            LL side=point[p];
            num[p]=1;
            while(side)
            {   
                if(!vis[to[side]])
                {
                    father[to[side]]=p;
                    deep[to[side]]=deep[p]+1;
                    dfs1(to[side]);
                    num[p]+=num[to[side]];
                    if(num[to[side]]>num[son[p]])son[p]=to[side];
                }
                side=next[side];
            }
        }
        inline const void dfs2(LL p,LL t)
        {
            vis[p]=true;top[p]=t;
            leaf[++order]=p;pos[p]=order;
            if(son[p]&&!vis[son[p]])dfs2(son[p],t);
            LL side=point[p];
            while(side)
            {
                if(!vis[to[side]]&&to[side]!=son[p])dfs2(to[side],to[side]);
                side=next[side];
            }
        }
        void solve()
        {
            memset(father,0,sizeof(father));
            memset(son,0,sizeof(son));
            memset(deep,0,sizeof(deep));
            memset(vis,false,sizeof(vis));
            dfs1(1);
            memset(vis,false,sizeof(vis));
            dfs2(1,1);
        }
    }link_cut_tree;
    struct SEGMENT_TREE
    {
        LL love[maxn<<2],col[maxn<<2],sum;
        inline const void update(LL p)
        {
            love[p]=max(love[p<<1],love[p<<1|1]);
        }
        inline const void build(LL p,LL l,LL r)
        {
            if(l==r){love[p]=init[leaf[++order]];return ;}
            LL mid=(l+r)>>1;
            build(p<<1,l,mid);
            build(p<<1|1,mid+1,r);
            update(p);
        }
        inline const void push_col(LL p)
        {
            if(col[p])
            {
                col[p<<1]+=col[p];col[p<<1|1]+=col[p];
                love[p<<1]+=col[p];love[p<<1|1]+=col[p];
                col[p]=0;
            }
        }
        inline const LL query(LL p,LL l,LL r,LL ll,LL rr)
        {
            if(l>=ll&&r<=rr)return love[p];
            push_col(p);
            LL mid=(l+r)>>1,ans=-INT_MAX;
            if(mid>=ll)ans=max(ans,query(p<<1,l,mid,ll,rr));
            if(mid+1<=rr)ans=max(ans,query(p<<1|1,mid+1,r,ll,rr));
            return ans;
        }
        inline const void modify(LL p,LL l,LL r,LL ll,LL rr,LL mark)
        {
            if(l>=ll&&r<=rr)
            {
                col[p]+=mark;love[p]+=mark;
                return ;
            }
            push_col(p);
            LL mid=(l+r)>>1;
            if(mid>=ll)modify(p<<1,l,mid,ll,rr,mark);
            if(mid+1<=rr)modify(p<<1|1,mid+1,r,ll,rr,mark);
            update(p);
        }
        void solve()
        {
            sum=order=0;
            build(1,1,n);
            memset(col,0,sizeof(col));
            while(t)
            {
                t--;
                LL start,end,ans=-INT_MAX,change;
                read(start);read(end);read(change);
                while(top[start]!=top[end])
                {
                    if(deep[top[start]]>deep[top[end]])
                    {
                        modify(1,1,n,pos[top[start]],pos[start],change);
                        ans=max(ans,query(1,1,n,pos[top[start]],pos[start]));
                        start=father[top[start]];
                    }
                    else
                    {
                        modify(1,1,n,pos[top[end]],pos[end],change);
                        ans=max(ans,query(1,1,n,pos[top[end]],pos[end]));
                        end=father[top[end]];
                    }
                }
                if(deep[start]>deep[end])
                {
                    modify(1,1,n,pos[end],pos[start],change);
                    ans=max(ans,query(1,1,n,pos[end],pos[start]));
                }
                else
                {
                    modify(1,1,n,pos[start],pos[end],change);
                    ans=max(ans,query(1,1,n,pos[start],pos[end]));
                }
                sum=(sum+ans)%mod;
            }
            write(sum);printf("\n");write(query(1,1,n,1,n));
        }
    }segment_tree;
    int main()
    {
        read(n);read(m);read(t);
        for(LL i=1;i<=n;i++)read(init[i]);
        least_tree.solve();
        link_cut_tree.solve();
        segment_tree.solve();
        return 0;
    }
    
  • 1

信息

难度
9
分类
(无)
标签
(无)
递交数
10
已通过
1
通过率
10%
上传者