이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |