[C++ map & dp]codeforces 960F. Pathwalks

题目传送门: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 }
View Code

下面整理一下map里好用的内置函数:

添加元素:

map<typename,typename>.insert( pair<typename,typename> ); // 注意参数是pair类型
返回一个pair类型,first成员是一个迭代器,second成员是一个bool值,true:插入成功 false:已存在
 
删除元素:
 
map.erase( k ); 
删除关键字为k的元素,返回删除的元素数量
map.erase( p );
删除迭代器p指定的元素,返回指向p之后的元素
map.erase(b,e);
删除迭代器对b,e之间的元素,返回e
 
查找元素:
 
map.upper_bound( k ); map.lower_bound( k );
以第一关键字比较大小,返回一个迭代器
map.equal_range(k);
返回一个迭代器pair,表示关键字等于k的范围。若不存在,都等于map.end()
 

猜你喜欢

转载自www.cnblogs.com/fanwl/p/10441124.html
今日推荐