Submission #422543

#TimeUsernameProblemLanguageResultExecution timeMemory
422543MetalPowerFinancial Report (JOI21_financial)C++14
100 / 100
710 ms40360 KiB
#include <bits/stdc++.h> using namespace std; // Observation #1 : If D = N, this problem is LIS // (supposedly we need to use segment tree) // (because of the additional constraints if D != N) // However the D will not always be N // Also there are some positions that we can't go to (because of the distance restriction) // Observation #2 : But, it is not correct to assume that we can only jump to positions with relative distance <= D // Because we can use the positions with value < curr as "stepping stones" // The farthest position we can jump to can be found in O(N log N) using DSU and sorting // sort the numbers and add the positions if val < curr // Join two positions if the distance < D // the farthest position in the DSU is the farthest position we can jump - D // So now we can simplify the problem as LIS in a bounded range // Observation #3 : We can solve this LIS in O(N log N) offline // solve the positions from the largest value // arr[curr] = rmq(curr + 1, curr + range[curr] + D) + 1 // Note that we have to solve positions with large value from the left // Because we need indexes that have value < curr_value // Observation #4 : the constraint p_{m} = N isn't important // because we can extend the LIS until p_{m} = N // if for example current p_{m} is A // We can add p_{m + 1} = A + 1, p_{m + 2} = A + 2, .. until p_{last} = N // Adding numbers will not decrease the impression score // Supposedly AC with time complexity O(N log N) #define pii pair<int, int> #define fi first #define se second const int MX = 3e5 + 100; inline void chmax(int& a, int b){ if(b > a) a = b; } struct segtree{ int seg[MX * 2]; segtree(){ memset(seg, 0, sizeof seg); } inline void upd(int p, int value){ // 0-based for(seg[p += MX] = value; p > 1; p >>= 1) seg[p >> 1] = max(seg[p], seg[p ^ 1]); } inline int range(int l, int r){ // 0-based [l, r] int res = 0; for(l += MX, r += MX + 1; l < r; l >>= 1, r >>= 1){ if(l & 1) chmax(res, seg[l++]); if(r & 1) chmax(res, seg[--r]); } return res; } } st; struct disjoint_set{ int par[MX], val[MX]; disjoint_set(){ for(int i = 0; i < MX; i++) val[i] = par[i] = i; } inline int f(int x){ if(par[x] == x) return x; else return par[x] = f(par[x]); } inline void Join(int u, int v){ int fu = f(u), fv = f(v); if(fu == fv) return; par[fu] = fv; chmax(val[fv], val[fu]); } inline int value(int x){ return val[f(x)]; } } dsu; int N, D, arr[MX], rg[MX], ans[MX]; vector<int> pos[MX]; int main(){ ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL); vector<int> v; cin >> N >> D; for(int i = 0; i < N; i++){ cin >> arr[i]; v.push_back(arr[i]); } sort(v.begin(), v.end()); v.resize(unique(v.begin(), v.end()) - v.begin()); for(int i = 0; i < N; i++) arr[i] = lower_bound(v.begin(), v.end(), arr[i]) - v.begin(); for(int i = 0; i < N; i++) pos[arr[i]].push_back(i); set<int> s; set<int>::iterator it; for(int i = 0; i < N; i++){ for(auto& a : pos[i]){ it = s.lower_bound(a); if(it != s.end() && (*it) - a <= D) dsu.Join(a, (*it)); if(it != s.begin()){ it--; if(a - (*it) <= D) dsu.Join(a, (*it)); } s.insert(a); } for(auto& a : pos[i]){ rg[a] = dsu.value(a); } } for(int i = N - 1; i >= 0; i--){ for(auto& a : pos[i]){ ans[a] = 1 + st.range(a + 1, min(N - 1, rg[a] + D)); st.upd(a, ans[a]); } } int sol = 0; for(int i = 0; i < N; i++) chmax(sol, ans[i]); cout << sol << '\n'; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...