2024.1.20 寒假训练记录(3)

今天上午开始做队友Younger发的专题题单,然后发现主席树忘记了好多又去复习,代码真的好难调qaq,下午打了集美大学的蓝桥杯校赛,刚拿到题解,明天补题

文章目录

  • CF 960F Pathwalks

CF 960F Pathwalks

题目链接

主席树中结点的lr表示左右子结点的编号而不是该结点的范围,要注意它和线段树的区别

#include 

using namespace std;

#define int long long

using i64 = long long;
using i128 = __int128_t;

typedef pair<int, int> PII;

const int N = 100010;

struct Node
{
    int l, r; // 指的是左右结点编号 不是左右范围
    int maxx;
}tr[N * 25];

int root[N], idx;

int query(int p, int l, int r, int limit) // 当前结点p,返回最长边不大于limit的最长路径边数
{
    if (l == r) return tr[p].maxx;
    int mid = l + r >> 1;
    if (mid >= limit) return query(tr[p].l, l, mid, limit);
    else return max(tr[tr[p].l].maxx, query(tr[p].r, mid + 1, r, limit));
}

void modify(int &p, int l, int r, int w, int res) // 当前是以p为根的子树中加上一条权值w的边,res是当前最长的边数
{
    if (!p) p = ++ idx;
    tr[p].maxx = max(tr[p].maxx, res);
    
    if (l == r) return;
    int mid = l + r >> 1;
    if (w <= mid) modify(tr[p].l, l, mid, w, res);
    else modify(tr[p].r, mid + 1, r, w, res);
}

void solve()
{
    int n, m;
    cin >> n >> m;
    vector<int> dp(m + 1);

    int ans = 0;
    for (int i = 1; i <= m; i ++ )
    {
        int u, v, w;
        cin >> u >> v >> w;
        dp[i] = query(root[u], 1, 100000, w - 1) + 1;
        modify(root[v], 1, 100000, w, dp[i]);
        ans = max(ans, dp[i]);
    }
    cout << ans << '\n';
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int t = 1;
    // cin >> t;
    while (t -- )
    {
        solve();
    }
}

你可能感兴趣的:(2024寒假训练记录,算法)