题目传送门
题意:
现在有n条带有权值的有向边,每条边表示从节点u到节点v的权值是w,第i条输入的边的编号是i。
这个图可能有自环,有重边,不保证连通。
现在让你找一条最长的路径,路径的长度是路径上有向边的个数。
按照这个有向路径的方向,每条路径上的边,编号严格递增,权值严格递增。
输出这个路径的长度。
题解:
S是一个有向边,则定义len(S)是以S为路径的初始边的最长路径长度。
这道题我是倒着做的,就是从编号大的到编号小的枚举。
对于当前边S,是通过满足下列条件的边T更新的。
(1)T的编号大于S的编号。
(2)T的起点是S的终点。即S可以直接到达T。
(3)T的权值大于S的权值。
找到以T为初始边的最长路径,可以去更新以S为初始边的最长路径长度。
即len(S) = max{len(T)} + 1。
最大的len(S)即为答案。
下面分析在当前情景下查找区间最大值的方法:
首先对于每个编号开一棵线段树,因为每个编号都有区间查询最大值的需求。
假设当前编号是x,那么开第x棵线段树时,线段树叶子节点的下标是权值,叶子节点存储的信息是路径长度。
我没有每棵线段树都开一个根节点,而是把每棵线段树维护的区间映射到一个大区间的一部分了,我觉得这样好维护。
感受:
这道题看了之后发现需要开1e5个线段树去维护,直接就爆空间了。
然后又不得不去学鸽了很久并且以为很难的动态开点线段树。
看了动态开点线段树博客后,秒懂,然后1A。(不过我的202ms真的比别人的都慢啊qwq)
原来是我看到它的名字把他想难了,其实和字典树的开点方式一模一样。
很久没有不看题解1A了,真的好爽。
题解:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll ;
const int maxn = 1e5 + 5 ;
const int maxm = 5e6 + 5 ;
int n , m ;
struct Edge
{
int u , v , w ;
} edge[maxn] ;
int root , cnt , ls[maxm] , rs[maxm] , max1[maxm] ;
void update(int &id , ll l , ll r , ll x , int y)
{
if(l > r) return ;
if(!id) id = ++ cnt ;
ll mid = (l + r) / 2 ;
if(l == r)
{
max1[id] = max(max1[id] , y) ;
return ;
}
if(x <= mid)
update(ls[id] , l , mid , x , y) ;
else
update(rs[id] , mid + 1 , r , x , y) ;
max1[id] = max(max1[ls[id]] , max1[rs[id]]) ;
}
int query(int id , ll l , ll r , ll x , ll y)
{
if(x > y) return 0 ;
if(!id) return 0 ;
int ans = 0 ;
ll mid = (l + r) / 2 ;
if(x <= l && r <= y)
return max1[id] ;
if(x <= mid) ans = max(ans , query(ls[id] , l , mid , x , y)) ;
if(y > mid) ans = max(ans , query(rs[id] , mid + 1 , r , x , y)) ;
return ans ;
}
int main()
{
int ans = 0 ;
ll len = 1e5 + 1 ;
scanf("%d%d" , &n , &m) ;
for(int i = 1 ; i <= m ; i ++)
scanf("%d%d%d" , &edge[i].u , &edge[i].v , &edge[i].w) , edge[i].w ++ ;
for(int i = m ; i >= 1 ; i --)
{
int u = edge[i].u , v = edge[i].v , w = edge[i].w ;
ll l = len * (v - 1) + w + 1 , r = len * (v - 1) + len ;
ll c = len * (u - 1) + w ;
ll x = query(root , 1 , len * len , l , r) ;
int y = x + 1 ;
update(root , 1 , len * len , c , y) ;
ans = max(ans , y) ;
}
printf("%d\n" , ans) ;
return 0 ;
}