F. Pathwalks动态开辟线段树

题意:n点m边,然后要求走最多的路,走路的时候经过的边权必须是严格递增。

解法1:传统的区间更新

解法2:发现区间更新只是对两个固定的点所延长形成的区间段,所以问题可以退化成单点更新单点查询。

然后动态开辟线段树就行了

线段树有1e5个然后每个都是权值线段树

解法一所需要的空间会比解法二大很多很多,甚至一度以为我写错了.....

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+88;
int rt[N],L[N*25],R[N*25],V[N*25],lz[N*25];
int n,m,tot;    
void update(int &k,int pos,int l,int r,int y){
    if(!k) k=++tot;
    if(l>=pos) {
        V[k]=max(y,V[k]);
        lz[k]=max(y,lz[k]);
        return;
    }
    if(lz[k]) {
        if(!L[k]) L[k]=++tot;if(!R[k]) R[k]=++tot;
        lz[L[k]]=max(lz[L[k]],lz[k]);
        lz[R[k]]=max(lz[k],lz[R[k]]);
        V[L[k]]=max(V[L[k]],lz[k]);
        V[R[k]]=max(V[R[k]],lz[k]);
        lz[k]=0;
    }
    int m=(l+r)>>1;
    if(pos<=m) update(L[k],pos,l,m,y);
    update(R[k],pos,m+1,r,y);
    V[k]=max(V[L[k]],V[R[k]]);
}
int query(int l,int r,int w,int k){
    if(!k) return 0;
    if(r<=w) return V[k];
    int m=(l+r)>>1;
    if(lz[k]) {
        if(!L[k]) L[k]=++tot;if(!R[k]) R[k]=++tot;
        lz[L[k]]=max(lz[L[k]],lz[k]);
        lz[R[k]]=max(lz[k],lz[R[k]]);
        V[L[k]]=max(V[L[k]],lz[k]);
        V[R[k]]=max(V[R[k]],lz[k]);
        lz[k]=0;
    }
    int ans=query(l,m,w,L[k]);
    if(w>m) ans=max(ans,query(m+1,r,w,R[k]));
    return ans;
}
int main(){
    scanf("%d%d",&n,&m);
    int x,y,z,ans=0;
    for(int i=1;i<=m;++i) {
        scanf("%d%d%d",&x,&y,&z);
        z+=10;
        int Q=query(1,100020,z-1,rt[x])+1;
        ans=max(ans,Q);
        update(rt[y],z,1,100020,Q);
    }
    printf("%d
",ans);
}
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+88;
int rt[N],L[N*20],R[N*20],V[N*20];
int n,m,tot;    
void update(int &k,int pos,int l,int r,int y){
    if(!k) k=++tot;
    V[k]=max(V[k],y);
    if(l==r) return;
    int m=(l+r)>>1;
    if(pos<=m) update(L[k],pos,l,m,y);
    else update(R[k],pos,m+1,r,y);
}
int query(int l,int r,int w,int k){
    if(!k) return 0;
    if(l==r) return V[k];
    int m=(l+r)>>1;
    if(w<=m) return query(l,m,w,L[k]);
    else return max(V[L[k]],query(m+1,r,w,R[k]));
}
int main(){
    scanf("%d%d",&n,&m);
    int x,y,z,ans=0;
    for(int i=1;i<=m;++i) {
        scanf("%d%d%d",&x,&y,&z);
        z+=10;
        int Q=query(1,100020,z-1,rt[x])+1;
        ans=max(ans,Q);
        update(rt[y],z,1,100020,Q);
    }
    printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/mfys/p/8796999.html