+ Problem : https://marisaoj.com/problem/276 Để giải quyết vấn đề, chúng ta cần biết tới thuật toán tìm LIS trong O(n * log(n)) và kĩ thuật small-to-large. Nhận xét : + Tại mỗi cây con gốc u, việc chọn 2 phần tử ở 2 nhánh sẽ không ảnh hưởng gì nhau. + Nếu chọn u thì ta sẽ trở thành bài toán LIS trên mảng. + Kết hợp với kĩ thuật "cute-lis" ta có thể giải quyết bài toán trong n * log^2(n). Sol : Tại mỗi cây con gốc u ta sẽ thêm tất cả phần tử tại multiset của các nhánh con vào u. Đối với u thì ta sẽ thực hiện như việc tìm LIS. Code mẫu : ```cpp #include <bits/stdc++.h> using namespace std; #define ll long long #define fi first #define sc second bool vis[100001]; vector<ll> adj[100001]; ll a[100001]; multiset<ll> se[100001]; ll n; void dfs(ll u){ if(vis[u]) return; vis[u]=true; ll cur_lis = 0; for (int v:adj[u]){ if (!vis[v]){ dfs(v); if(se[u].size() < se[v].size()){ se[u].swap(se[v]); } for (auto i : se[v]) se[u].insert(i); } } se[u].insert(a[u]); auto it = se[u].find(a[u]); it++; if(it!=se[u].end()){ se[u].erase(it); } } void inp(){ cin >> n; for (int i=1;i<=n;i++) { cin >> a[i]; } for (int i=1;i<n;i++){ ll u,v; cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); } } void solve(){ inp(); memset(vis , false ,sizeof vis); dfs(1); cout << se[1].size(); } int main(){ ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); solve(); } ```