【题解】P3364 Cool loves touli

P3364】题解

一:【题面】

二:【解法】

每个点有属性{l,a,b,c}表{等级,力量,智力,攻击力}
dp[i]:前i个点最长合法序列
dp[i]=max(dp[j]+1),l[j]<l[i],c[j]<=a[i],b[j]<=c[i]
三维偏序优化,用前缀max树状数组维护

三:【代码】

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node{
	int l,a,b,c;
	int ans;
}q[N];
bool cmpl(node x,node y){
	if(x.l!=y.l) return x.l<y.l;
	if(x.c!=y.a) return x.c<y.a;
	return x.b<y.c;
}
bool cmpc(node x,node y){
	return x.c<y.c;
}
bool cmpa(node x,node y){
	return x.a<y.a;
}
int tree[3*N];
void update(int x,int d){
	while(x<3*N){
		tree[x]=max(tree[x],d);
		x+=x&-x;
	}
}
int query(int x){
	int res=0;
	while(x){
		res=max(res,tree[x]);
		x-=x&-x;
	}
	return res;
}
void re(int x){
	while(x<3*N){
		tree[x]=0;
		x+=x&-x;
	}
}
void CDQ(int l,int r){
	if(l==r){
		q[l].ans=max(q[l].ans,1);
		return ;
	}
	int mid=l+r>>1;
	CDQ(l,mid);
	sort(q+l,q+mid+1,cmpc);sort(q+mid+1,q+r+1,cmpa);
	
	int i=l,j=mid+1;
	while(j<=r){
		while(i<=mid&&q[i].c<=q[j].a){
			update(q[i].b,q[i].ans);
			i++;
		}
		q[j].ans=max(q[j].ans,query(q[j].c)+1);
		j++;
	}
	for(int k=l;k<i;k++) re(q[k].b);
	sort(q+mid+1,q+r+1,cmpl);
	
	CDQ(mid+1,r);
}
int main(){
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	int n;cin>>n;
	
	vector<int> lsh;
	for(int i=1;i<=n;i++){
		int l,a,b,c;cin>>l>>a>>b>>c;
		lsh.push_back(a);
		lsh.push_back(b);
		lsh.push_back(c);
		q[i]={l,a,b,c,0};
	}
	sort(lsh.begin(),lsh.end());lsh.erase(unique(lsh.begin(),lsh.end()),lsh.end());
	for(int i=1;i<=n;i++) q[i].a=lower_bound(lsh.begin(),lsh.end(),q[i].a)-lsh.begin()+1;
	for(int i=1;i<=n;i++) q[i].b=lower_bound(lsh.begin(),lsh.end(),q[i].b)-lsh.begin()+1;
	for(int i=1;i<=n;i++) q[i].c=lower_bound(lsh.begin(),lsh.end(),q[i].c)-lsh.begin()+1;
	
	sort(q+1,q+1+n,cmpl);
	CDQ(1,n);
	
	int ans=0;
	for(int i=1;i<=n;i++){
		ans=max(ans,q[i].ans);
	}
	cout<<ans<<"\n";
	return 0;
}
posted @ 2025-12-27 09:19  Ming3398  阅读(3)  评论(0)    收藏  举报