这是一个三维问题,通过对问题分析,可以得到非常板的式子
d p [ i ] = 1 + m a x j = 1 i − 1 d p j [ a j < a i ] [ b j < b i ] dp[i]=1+max^{i-1}_{j=1}dp_j[a_j<a_i][b_j<b_i] dp[i]=1+maxj=1i−1dpj[aj<ai][bj<bi]
再然后就是考虑用CDQ将时间复杂度降下来。
对于一个区间 l l l~ r r r内的dp计算,首先通过对第一维的排序就可以保证dp[i]决策在1到i-1内。
将区间二分考虑,当i位于区间右边时候,需要先通过双指针来用左区间的决策更新i,这就要求左区间内所有的决策点dp都已经计算好了。所以在双指针计算之前,我们需要先递归处理左边。而为什么在双指针计算后再递归右边,可以这样考虑,右区间里大于i的dp值的更新需要求dp[i]已经完全计算完毕,但如果先递归右边区间,那么显然在递归右边区间的时候i处的dp值是没有计算完成的,还缺少左区间的这一部分决策点,但更新大于i的dp值只能通过递归右边,无法反悔更新,也就会出现计算遗漏。
这道题只需要用树状数组维护最大前缀值就可以了,另外有坑点就是空间需要开到3N,因为有每个点有3个值,然后离散后树状数组最大到3N。
#include<bits/stdc++.h>
using namespace std;
#define se second
#define fi first
#define LINF 0x3f3f3f3f3f3f3f3f
#define INF 0x3f3f3f3f
#define ll long long
#define ull unsigned long long
#define pii pair<ll,ll>
const int mod=998244353;
const int N=500005;
struct node{
ull a,b,c;
int id;
}nd[N],nd2[N];
int maxlen;
int maxn;
node temp1[N],temp2[N];
int dp[N];
bool cmp(node &a,node &b){
return a.b<b.b;
}
int lowbit(int x){
return x&(-x);
}
int tree[N];
int n;
void add(int x,int c){
for(;x<=maxlen;x+=lowbit(x))tree[x]=max(tree[x],c);
}
void del(int x){
for(;x<=maxlen;x+=lowbit(x))tree[x]=-1;
}
int querry(int x){
int res=-1;
for(;x;x-=lowbit(x))res=max(tree[x],res);
return res;
}
void CDQ(int l,int r){
if(l>=r)return;
int mid=l+r>>1;
CDQ(l,mid);
for(int i=l;i<=mid;i++){
temp1[i-l+1]=nd2[i];
}
for(int i=mid+1;i<=r;i++){
temp2[i-mid]=nd2[i];
}
sort(temp1+1,temp1+mid-l+1+1,cmp);
sort(temp2+1,temp2+r-mid+1,cmp);
int i=1,j=1;
while(j<=r-mid){
while(i<=mid-l+1&&temp1[i].b<=temp2[j].b){
add(temp1[i].c,dp[temp1[i].id]);i++;
}
dp[temp2[j].id]=max(dp[temp2[j].id],querry(temp2[j].c)+1);
maxn=max(dp[temp2[j].id],maxn);
j++;
}
for(int l1=1;l1<i;l1++)del(temp1[l1].c);
CDQ(mid+1,r);
return;
}
unsigned long long k1, k2;
unsigned long long CoronavirusBeats() {
unsigned long long k3 = k1, k4 = k2;
k1 = k4;
k3 ^= k3<<23;
k2 = k3 ^ k4 ^ (k3>>17) ^ (k4>>26);
return k2 + k4;
}
void solve(){
memset(tree,-1,sizeof tree);
cin>>n>>k1>>k2;
vector<ull>vec;
for (int i = 1; i <= n; ++i) {
nd[i].a = CoronavirusBeats();
nd[i].b = CoronavirusBeats();
nd[i].c = CoronavirusBeats();
vec.push_back(nd[i].a);
vec.push_back(nd[i].b);
vec.push_back(nd[i].c);
}
sort(vec.begin(),vec.end());
vec.erase(unique(vec.begin(),vec.end()),vec.end());
for(int i=1;i<=n;i++){
nd2[i].a=lower_bound(vec.begin(),vec.end(),nd[i].a)-vec.begin()+1;
nd2[i].b=lower_bound(vec.begin(),vec.end(),nd[i].b)-vec.begin()+1;
nd2[i].c=lower_bound(vec.begin(),vec.end(),nd[i].c)-vec.begin()+1;
nd2[i].id=i;
}
maxlen=vec.size();
sort(nd2+1,nd2+1+n,[&](node a,node b){
if(a.a!=b.a)return a.a<b.a;
if(a.b!=b.b)return a.b<b.b;
return a.c<b.c;
});
CDQ(1,n);
cout<<maxn+1<<"\n";
for(int i=1;i<=n;i++){
cout<<dp[i]<<' ';
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
solve();
return 0;
}