CF960F Pathwalks(线段树)

思路的转换还是比较重要。

虽然本题有两个条件需要控制,但是我们发现第一个条件是根据输入顺序来的,那么就会产生一个猜想,如果边输边做,那么只需要维护第二个条件就可以了。

第二个条件是权值为递增,这个非常像dp中的最长上升子串,但是由于本题是图,所以不能用dp方程做,但是可以借鉴一下。

我们在做dp的时候,都是设计状态以哪个点为终点的最大值,对于本题我们也如法炮制。只需要求出到出发点边的权值小于他的最长路就能用这个与答案进行比较。

我们可以考虑线段树,对于每个点维护到他的最后一条边权值为i的最大值。因为数据大,考虑动态开点

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int inf=0x3f3f3f3f;
int rt[N];
int tot;
struct node{
    int l,r;
    int sum;
}tr[N*24];
void pushup(int u){
    tr[u].sum=max(tr[tr[u].l].sum,tr[tr[u].r].sum);
}
void modify(int u,int x,int l,int r,int &rt){
    if(!rt)
        rt=++tot;
    if(l==r){
        tr[rt].sum=max(tr[rt].sum,x);
        return ;
    }
    int mid=l+r>>1;
    if(u<=mid)
        modify(u,x,l,mid,tr[rt].l);
    else
        modify(u,x,mid+1,r,tr[rt].r);
    pushup(rt);
}
int query(int L,int R,int l,int r,int &rt){
    if(!rt)
        return 0;
    if(L<=l&&R>=r){
        return tr[rt].sum;
    }
    int mid=l+r>>1;
    int ans=0;
    if(L<=mid){
        ans=query(L,R,l,mid,tr[rt].l);
    }
    if(R>mid)
        ans=max(ans,query(L,R,mid+1,r,tr[rt].r));
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    int i;
    int n,m;
    cin>>n>>m;
    ll ans=0;
    for(i=1;i<=m;i++){
        int a,b,c;
        cin>>a>>b>>c;
        ll res=query(0,c-1,0,100000,rt[a])+1;
        ans=max(ans,res);
        modify(c,res,0,100000,rt[b]);
    }
    cout<<ans<<endl;
}
View Code

 

posted @ 2020-10-10 19:59  朝暮不思  阅读(151)  评论(0编辑  收藏  举报