• poj3162(树形dp+线段树求最大最小值)


    题目链接:https://vjudge.net/problem/POJ-3162

    题意:给一棵树,求每个结点的树上最远距离,记为a[i],然后求最大区间[l,r]满足区间内的max(a[i])-min(a[i])<=M。

    思路:第一步向hdoj2196那题一样树形dp求出每个结点的最长距离,我的另一篇博客中有写到https://www.cnblogs.com/FrankChen831X/p/11375572.html。求出最远距离a[i]后,建立线段树维护区间的最大最小值。然后用两个指针i,j遍历一遍,每次求出[i,j]的最大最小值ans1和ans2,更新答案,因为j每次不用初始化,总复杂度为O(nlogn)。

    AC代码:

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const int maxn=1e6+5;
    const LL inf=0x3f3f3f3f3f3f3f3f;
    int n,ans,cnt,head[maxn],pt[maxn],a[maxn];
    LL M,dp[maxn][3],ans1,ans2;
    
    struct node1{
        int v,nex;
        LL w;
    }edge[maxn<<1];
    
    struct node2{
        int l,r;
        LL Max,Min;
    }tr[maxn<<2];
    
    void adde(int u,int v,LL w){
        edge[++cnt].v=v;
        edge[cnt].w=w;
        edge[cnt].nex=head[u];
        head[u]=cnt;
    }
    
    void dfs1(int u,int fa){
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            LL w=edge[i].w;
            if(v==fa) continue;
            dfs1(v,u);
            if(w+dp[v][0]>dp[u][0]){
                dp[u][1]=dp[u][0];
                dp[u][0]=w+dp[v][0];
                pt[u]=v;
            }
            else if(w+dp[v][0]>dp[u][1])
                dp[u][1]=w+dp[v][0];
        }
    }
    
    void dfs2(int u,int fa){
        for(int i=head[u];i;i=edge[i].nex){
            int v=edge[i].v;
            LL w=edge[i].w;
            if(v==fa) continue;
            if(v!=pt[u])
                dp[v][2]=w+max(dp[u][0],dp[u][2]);
            else 
                dp[v][2]=w+max(dp[u][1],dp[u][2]);
            dfs2(v,u);
        }
    }
    
    void pushup(int v){
        tr[v].Max=max(tr[v<<1].Max,tr[v<<1|1].Max);
        tr[v].Min=min(tr[v<<1].Min,tr[v<<1|1].Min);
    }
    
    void build(int v,int l,int r){
        tr[v].l=l,tr[v].r=r;
        if(l==r){
            tr[v].Max=tr[v].Min=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(v<<1,l,mid);
        build(v<<1|1,mid+1,r);
        pushup(v);
    }
    
    void query(int v,int l,int r){
        if(l<=tr[v].l&&r>=tr[v].r){
            ans1=max(ans1,tr[v].Max);
            ans2=min(ans2,tr[v].Min);
            return;
        }
        int mid=(tr[v].l+tr[v].r)>>1;
        if(l<=mid) query(v<<1,l,r);
        if(r>mid) query(v<<1|1,l,r);
    }
    
    int main(){
        scanf("%d%lld",&n,&M);
        for(int i=2;i<=n;++i){
            int v;LL w;
            scanf("%d%lld",&v,&w);
            adde(i,v,w);
            adde(v,i,w);
        }
        dfs1(1,0);
        dfs2(1,0);
        for(int i=1;i<=n;++i)
            a[i]=max(dp[i][0],dp[i][2]);
        build(1,1,n);
        int j=1;
        for(int i=1;i<=n;++i){
            while(j<=n){
                ans1=0,ans2=inf;
                query(1,i,j);
                if(ans1-ans2>M) break;
                ++j;
            }
            ans=max(ans,j-i);
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    LeetCode 769. Max Chunks To Make Sorted
    LeetCode 845. Longest Mountain in Array
    LeetCode 1059. All Paths from Source Lead to Destination
    1129. Shortest Path with Alternating Colors
    LeetCode 785. Is Graph Bipartite?
    LeetCode 802. Find Eventual Safe States
    LeetCode 1043. Partition Array for Maximum Sum
    LeetCode 841. Keys and Rooms
    LeetCode 1061. Lexicographically Smallest Equivalent String
    LeetCode 1102. Path With Maximum Minimum Value
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/11423208.html
Copyright © 2020-2023  润新知