Divide by Zero 2018 and Codeforces Round #474 (Div. 1 + Div. 2, combined)

思路:把边看成点,然后每条边只能从下面的边转移过来,我们将边按照u为第一关键字,w为第二关键字排序,这样就能用线段树维护啦。

  1 #include<bits/stdc++.h>
  2 #define LL long long
  3 #define fi first
  4 #define se second
  5 #define mk make_pair
  6 #define pii pair<int,int>
  7 using namespace std;
  8 
  9 const int N = 1e6 + 7;
 10 const int M = 100 + 7;
 11 const int inf = 0x3f3f3f3f;
 12 const LL INF = 0x3f3f3f3f3f3f3f3f;
 13 const int mod = 1e9 + 7;
 14 
 15 
 16 int n, m, hs[N];
 17 
 18 struct node {
 19     int u, v, w;
 20     node(int u = 0, int v = 0, int w = 0) {
 21         this -> u = u;
 22         this -> v = v;
 23         this -> w = w;
 24     }
 25     bool operator < (const node &rhs) const {
 26         if(u == rhs.u) {
 27             return w < rhs.w;
 28         } else {
 29             return u < rhs.u;
 30         }
 31     }
 32 } edge[N], edge2[N];
 33 
 34 
 35 struct seg_tree {
 36     struct node {
 37         int mx, l, r;
 38     }a[N << 2];
 39 
 40     void build(int l, int r, int rt) {
 41         a[rt].l = l, a[rt].r = r;
 42         if(l == r) return;
 43         int mid = (l + r) >> 1;
 44         build(l, mid, rt << 1);
 45         build(mid + 1, r, rt << 1 | 1);
 46     }
 47 
 48     void update(int pos, int rt, int v) {
 49         int l = a[rt].l, r = a[rt].r;
 50         if(l == r) {
 51             a[rt].mx = max(a[rt].mx, v);
 52             return;
 53         }
 54 
 55         int mid = (l + r) >> 1;
 56 
 57         if(pos <= mid)
 58             update(pos, rt << 1, v);
 59         else
 60             update(pos, rt << 1 | 1, v);
 61 
 62         a[rt].mx = max(a[rt << 1].mx, a[rt << 1 | 1].mx);
 63     }
 64 
 65     int query(int L, int R, int rt) {
 66         int l = a[rt].l, r = a[rt].r;
 67         if(l >= L && r <= R) {
 68             return a[rt].mx;
 69         }
 70 
 71         int mid = (l + r) >> 1;
 72         int ans = 0;
 73 
 74         if(L <= mid)
 75             ans = max(ans, query(L, R, rt << 1));
 76         if(R > mid)
 77             ans = max(ans, query(L, R, rt << 1 | 1));
 78 
 79         return ans;
 80     }
 81 }seg;
 82 
 83 int main() {
 84 
 85     scanf("%d%d", &n, &m);
 86 
 87     for(int i = 1; i <= m; i++) {
 88         scanf("%d", &edge[i].u);
 89         scanf("%d", &edge[i].v);
 90         scanf("%d", &edge[i].w);
 91         edge2[i].u = edge[i].u;
 92         edge2[i].v = edge[i].v;
 93         edge2[i].w = edge[i].w;
 94     }
 95 
 96     sort(edge2 + 1, edge2 + m + 1);
 97     int ans = 0;
 98 
 99     seg.build(1, m, 1);
100     for(int i = m; i >= 1; i--) {
101         int l = lower_bound(edge2 + 1, edge2 + m + 1, node(edge[i].v, 0, edge[i].w + 1)) - edge2;
102         int r = lower_bound(edge2 + 1, edge2 + m + 1, node(edge[i].v + 1, 0, -1)) - edge2 - 1;
103         int ret = 1;
104         if(l <= r) {
105             ret = max(ret, 1 + seg.query(l, r, 1));
106         }
107         int pos = lower_bound(edge2 + 1, edge2 + m + 1, edge[i]) - edge2;
108         seg.update(pos, 1, ret);
109     }
110 
111     printf("%d\n", seg.a[1].mx);
112     return 0;
113 }
114 
115 /*
116 */

 

转载于:https://www.cnblogs.com/CJLHY/p/8761154.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值