#include <bits/stdc++.h>
#define long long long
using namespace std;
const long INF = (long)1e18;
void init() {
#define task "main"
if (fopen(task".INP","r")) {
freopen(task".INP","r",stdin);
freopen(task".OUT","w",stdout);
}
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
struct SegTree {
int n;
vector<long> st;
SegTree(int _n): n(_n), st(4*_n, -INF) {}
void update(int p, long v) { update(1,1,n,p,v); }
void update(int node,int l,int r,int p,long v){
if(l==r){ st[node]=v; return; }
int m=(l+r)>>1;
if(p<=m) update(node<<1,l,m,p,v);
else update(node<<1|1,m+1,r,p,v);
st[node]=max(st[node<<1], st[node<<1|1]);
}
long query(int i,int j){ return query(1,1,n,i,j); }
long query(int node,int l,int r,int i,int j){
if(i>r||j<l) return -INF;
if(i<=l&&r<=j) return st[node];
int m=(l+r)>>1;
return max(query(node<<1,l,m,i,j),
query(node<<1|1,m+1,r,i,j));
}
// tìm chỉ số nhỏ nhất j in [i..n] sao cho st[j] >= x; nếu không có trả về n+1
int find_first(int i, long x) { return find_first(1,1,n,i,x); }
int find_first(int node,int l,int r,int i,long x){
if(r<i || st[node]<x) return n+1;
if(l==r) return l;
int m=(l+r)>>1;
int t = find_first(node<<1, l, m, i, x);
if(t<=m) return t;
return find_first(node<<1|1, m+1, r, i, x);
}
};
int main(){
init();
int N, D;
cin >> N >> D;
vector<long> A(N+1);
for(int i=1;i<=N;i++) cin >> A[i];
// 1) Tính M[j] = max(A[j-D]..A[j]) với deque
vector<long> M(N+1, -INF);
deque<int> dq;
for(int j=1;j<=N;j++){
while(!dq.empty() && dq.front() < j-D) dq.pop_front();
while(!dq.empty() && A[dq.back()] <= A[j]) dq.pop_back();
dq.push_back(j);
if(j>=D+1) M[j] = A[dq.front()];
}
// 2) Build seg-tree trên M để tìm R[i]
SegTree stM(N);
for(int j=D+1;j<=N;j++){
stM.update(j, M[j]);
}
vector<int> R(N+1);
for(int i=1;i<=N;i++){
int L = i + D + 1;
if(L > N){
R[i] = N;
} else {
// tìm j đầu tiên >= L sao cho M[j] >= A[i]+1
int j = stM.find_first(L, A[i]+1);
R[i] = (j<=N ? j-1 : N);
}
}
// 3) DP với seg-tree trên dp[]
SegTree st_dp(N);
vector<pair<long,int>> order;
order.reserve(N);
for(int i=1;i<=N;i++) order.emplace_back(-A[i], i);
sort(order.begin(), order.end()); // giảm dần A, nếu bằng tăng i
vector<long> dp(N+1, 0);
long answer = 0;
for(auto &pr : order){
int i = pr.second;
int l = i+1, r = R[i];
long best = 0;
if(l <= r) best = st_dp.query(l,r);
dp[i] = best + 1;
st_dp.update(i, dp[i]);
answer = max(answer, dp[i]);
}
cout << answer << "\n";
return 0;
}
컴파일 시 표준 에러 (stderr) 메시지
Main.cpp: In function 'void init()':
Main.cpp:10:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
10 | freopen(task".INP","r",stdin);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
Main.cpp:11:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
11 | freopen(task".OUT","w",stdout);
| ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
# | 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... |