2025年11月29日训练赛
P13968 [VKOSHP 2024] Classics
倒着找每个的最终位置,二分+树状数组求第k大,这样把序列搞出来
再找最长上升子序列,从小往大往树状数组里面加,找前面的最长上升子序列+1 不可以从前往后往树状数组里加,找比他小的的最长上升子序列+1,加入的顺序不对
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define yes cout << "Yes" << endl
#define no cout << "No" << endl
#define pii pair<int,int>
#define ll long long
#define pb push_back
#define ft first
#define se second
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define int long long
const int N = 200010;int n;
int p[N], mp[N], a[N];
int lowbit(int x){return x&(-x);}
int tr1[N];
void add1(int x, int k){
for(int i = x; i <= n; i += lowbit(i)) tr1[i] += k;
}
int ask1(int x){
int res = 0; for(int i = x; i > 0; i -= lowbit(i)) res += tr1[i]; return res;
}
int tr2[N];
void add2(int x, int k){
for(int i = x; i <= n; i += lowbit(i)) tr2[i] = max(tr2[i], k);
}
int ask2(int x){
if(!x) return 0;
int res = 0;
for(int i = x; i > 0; i -= lowbit(i)) res = max(res, tr2[i]); return res;
}
void solve(){
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) add1(i, 1);
for(int i = n; i >= 1; i --){
int x = a[i];
int l = 1; int r = n;
while(l < r){
int mid = (l + r) >> 1;
if(ask1(mid) >= x) r = mid;
else l = mid + 1;
}
//cout << "get" << l << '\n';
p[l] = i;
mp[i] = l;
add1(l, -1);
}
// for(int i = 1; i <= n; i ++) cout << p[i] << ' '; cout << '\n';
int ans = 1;
for(int i = 1; i <= n; i ++){
int t = ask2(mp[i] - 1) + 1;
ans = max(ans, t);
cout << ans << '\n';
add2(mp[i], t);
}
}
signed main(){
std::ios::sync_with_stdio(false);
int T = 1;// cin >> T;
while(T--){
solve();
}
}

浙公网安备 33010602011771号