【题解】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;
}

浙公网安备 33010602011771号