标签:ase cout vector pac 序列 数据 fine namespace opened
题目传送门:960F
思路:
题目给人的感觉很像最长上升子序列,自然而然想到用dp的思路去处理
题目中给的限制条件是,要接上前面的边,前面的边权一定要小于当前的边权(题目按照输入的顺序,因此只找前面的边)
对于每个结点,我们要维护的信息是:
当前状态下,w的边权到达这个点,最多能有几条边
如何维护这个信息呢?如果对每个点开一个maxn的数组,每次暴力修改,显然是过不去的
一种处理办法是:对每个点建动态线段树(可是本菜鸡不会!!。。我马上去学
另一种简单的处理办法:用map以及map内置的函数
对每个点建立一个map<int,int> 保存对应边权下,能达到的最大的边数
vector< map<int,int> > s; ... s.resize(n+1);
对于每条边(a,b,w), 查a点的map里,小于w 的最大的边数
1 int get_edge_no(int a,int w){ 2 auto t = s[a].lower_bound(w); 3 if(t == s[a].begin())return 0; 4 --t; 5 return t->second; 6 }
然后得到b对应的w的结果,再保存至b的map里
1 int t = get_edge_no(a,w) + 1; 2 if(t < get_edge_no(b,w+1))continue; 3 s[b][w] = t;
保存之后,一定要将map里w大 val小的元素删除(因为这部分数据也需要更新)
1 auto it = s[b].upper_bound(w); 2 while(it != s[b].end() && it->second < t){ 3 it = s[b].erase(it); 4 } 5 ans = max(ans,t);
完整代码:
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 #define _____ ios::sync_with_stdio(false);cin.tie(0); 5 int n,m; 6 const int maxn = 100005; 7 vector< map<int,int> > s; 8 int get_edge_no(int a,int w){ 9 auto t = s[a].lower_bound(w); 10 if(t == s[a].begin())return 0; 11 --t; 12 return t->second; 13 } 14 int main(){ 15 //freopen("data.in","r",stdin); 16 _____ 17 cin >> n >> m; 18 s.resize(n+1); 19 int a,b,w; 20 int ans = 0; 21 for(int i = 1; i <= m; i++){ 22 cin >> a >> b >> w; 23 int t = get_edge_no(a,w) + 1; 24 if(t < get_edge_no(b,w+1))continue; 25 s[b][w] = t; 26 auto it = s[b].upper_bound(w); 27 while(it != s[b].end() && it->second < t){ 28 it = s[b].erase(it); 29 } 30 ans = max(ans,t); 31 } 32 cout << ans << ‘\n‘; 33 return 0; 34 }
下面整理一下map里好用的内置函数:
添加元素:
[C++ map & dp]codeforces 960F. Pathwalks
标签:ase cout vector pac 序列 数据 fine namespace opened
原文地址:https://www.cnblogs.com/fanwl/p/10441124.html