Codeforces 960F Pathwalks ( LIS && 树状数组 )
题意 : 给出若干个边,每条边按照给出的顺序编号,问你找到一条最长的边权以及边的编号同时严格升序的一条路径,要使得这条路径包含的边尽可能多,最后输出边的条数
分析 :
这题和 LIS 很相似,不同的是加多了一个需要边和边相连这一条件
考虑使用树状数组求 LIS 的方法来考虑这题
如果你还不知道 LIS 还能用树状数组做 ==> Click here
由于有了只有能够构成路径的边才能搭配成子序列这一限制
我们将原本一维的树状数组开成二维
增加的维度表示以某个图中顶点为结尾这一状态
定义二维树状数组 c[Node][Weight]
表示以顶点(图中的顶点) Node 为结尾、边权为 Weight 时候的 LIS 长度
然后对于边 (a、b、w) 用 c[a][w] + 1 去更新 c[b][w] 即可
更新过程类似树状数组求解 LIS 问题一样
最后就是这题貌似还能用主席树等可持久化数据结构做
待我研究后补上.......
#include<bits/stdc++.h> #define lowbit(i) (i & (-i)) using namespace std; const int maxn = 1e5 + 5; const int INF = 0x3f3f3f3f; map<int, int> c[maxn];///1e5的二维数组开不下、采用map来代替开 int N, M; int query(int i, int w) { int ret = 0; while(w > 0){ ret = max(ret, c[i][w]); w -= lowbit(w); } return ret; } void update(int i, int w, int val)///update的时候注意w不能为 0 { while(w < maxn){ c[i][w] = max(c[i][w], val); w += lowbit(w); } } int main(void) { scanf("%d %d", &N, &M); int a, b, w, MX = -INF; for(int i=1; i<=M; i++){ scanf("%d %d %d", &a, &b, &w); MX = max(MX, ++w); update(b, w, query(a, w-1)+1); } int ans = 0; for(int i=1; i<=N; i++) ans = max(ans, query(i, MX)); printf("%d\n", ans); return 0; }