专栏文章
题解:P13968 [VKOSHP 2024] Classics
P13968题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @mjxqsh8j
- 此快照首次捕获于
- 2026/01/03 11:27 2 个月前
- 此快照最后确认于
- 2026/01/03 11:27 2 个月前
双倍经验:P4309 [TJOI2013] 最长上升子序列。话说凭啥这题是蓝,那题是紫。
分析
我们需要在每次插入时获得 LIS。
我们可以直接模拟得到所有插入操作之后的序列。
然后枚举每一个数。由于是按顺序插入,所以先处理小的,再处理大的,就不会影响答案。
用 表示 在最终数组中的位置,维护 ,即 数组中 的最大值即可。最后更新一下 就行了。
那我万一有一个 满足 怎么办
这时候 还没有插入,没有影响。
你可以使用 rope 或者支持分裂的平衡树维护。注意 rope 的下标是 0 开始的。
注意!线段树无法处理 这种无效区间,所以记得特判 。
CPP#include<bits/extc++.h>
#define endl '\n'
using namespace std;
using namespace __gnu_cxx;
rope<int> r;
const int maxn=2e5+5;
struct T{
struct node{
int l,r,max;
}t[maxn*4];
#define ls id<<1
#define rs id<<1|1
void up(int id){t[id].max=max(t[ls].max,t[rs].max);}
void build(int id,int l,int r){
t[id].l=l,t[id].r=r;
if(l==r){
t[id].max=0;
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
up(id);
}
int query(int id,int l,int r){
if(t[id].l>r||t[id].r<l)return INT_MIN;
if(l<=t[id].l&&t[id].r<=r)return t[id].max;
return max(query(ls,l,r),query(rs,l,r));
}
void update(int id,int x,int val){
if(t[id].l>x||t[id].r<x)return;
if(t[id].l==t[id].r&&t[id].l==x){t[id].max=val;return;}
update(ls,x,val);update(rs,x,val);
up(id);
}
}t;
int ans[maxn],pos[maxn];
int main(){
int n;
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){int x;cin>>x;r.insert(x-1,i);}
for(int i=0;i<n;i++)pos[r[i]]=i+1;
t.build(1,1,n);
for(int i=1;i<=n;i++){//枚举K
if(pos[i]==1)ans[i]=1;//特判!
else ans[i]=t.query(1,1,pos[i]-1)+1;//[1,pos_i)
t.update(1,pos[i],ans[i]);
}
for(int i=1;i<=n;i++){
ans[i]=max(ans[i],ans[i-1]);
cout<<ans[i]<<endl;
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...