[CF960F]Pathwalks

Posted slrslr

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF960F]Pathwalks相关的知识,希望对你有一定的参考价值。

题目大意:给你一张$n$个点$m$条边的带权有向图,可能有重边和自环。边会按照顺序给出。让你求出一条最长的路径,使得路径上的边满足边权和出现的时间严格递增。路径可以重复经过同一个点。

想办法把它转化成序列上的最长上升序列

我们如果按顺序加边,那么边做边求是符合边的出现时间递增的要求的

所以当给你一条边$a$->$b$边权为$c$时,我们要在合理的复杂度内查到到$a$点边权小于$c$的最长上升序列

然后用它去更新答案和到$b$边权小于等于$c$的最大值

这显然是个线段树,然后我们再搞个动态开点,完事

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #define M 500010
 5 #define ls ch[node][0]
 6 #define rs ch[node][1]
 7 using namespace std;
 8 int read()
 9 {
10     char ch=getchar();int x=0;
11     while(ch>9||ch<0) ch=getchar();
12     while(ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar();
13     return x;
14 }
15 int n,m,cnt,ans;
16 int root[M],val[M<<2],ch[M<<2][2];
17 void insert(int &node,int l,int r,int k,int x)
18 {
19     if(!node) node=++cnt;
20     val[node]=max(val[node],x);
21     if(l==r) return;
22     int mid=(l+r)/2;
23     if(k<=mid) insert(ls,l,mid,k,x);
24     else insert(rs,mid+1,r,k,x);
25 }
26 int query(int node,int l,int r,int l1,int r1)
27 {
28     if(!node) return 0;
29     if(l1>r||r1<l) return 0;
30     if(l1<=l&&r1>=r) return val[node];
31     int mid=(l+r)/2;
32     return max(query(ls,l,mid,l1,r1),query(rs,mid+1,r,l1,r1));
33 }
34 int main()
35 {
36     n=read();m=read();
37     for(int i=1;i<=m;i++)
38     {
39         int a=read(),b=read(),z=read()+1;
40         int x=query(root[a],1,100000,1,z-1)+1;
41         ans=max(ans,x);
42         insert(root[b],1,100001,z,x);
43     }
44     printf("%d",ans);
45     return 0;
46 }

 

以上是关于[CF960F]Pathwalks的主要内容,如果未能解决你的问题,请参考以下文章

CodeForces - 960F Pathwalks —— 主席树(n棵线段树)

Pathwalks CodeForces - 960F(主席树 || 树状数组)

cf960F

如何从后台弹出片段

cf 模拟

CF1435 游记