P5621 [DBOI2019] 德丽莎世界第一可爱
前言
我们可以发现这就是一个四维偏序,那么我们就可以采用 cdq 套 cdq 来解决它,然后这里还有两个双倍经验。
思路
我们可以得出一个 \(n^2\) dp,用 \(f_i=\max(f_j+val_i)\) 其中的 \(j\) 要满足四维不大于 \(i\)。
首先我们可以一维一维的来考虑。
对于第一维,和三位偏序一样直接排序即可。
il bool cmpa(node a,node b) {
if(a.a!=b.a) return a.a<b.a;
if(a.b!=b.b) return a.b<b.b;
if(a.c!=b.c) return a.c<b.c;
return a.d<b.d;
}
然后我们就需要来考虑如何既保证第 \(1\) 维有序有保证第 \(2\) 维有序,这里我们可以采用一种标记的形式(毕竟我们只需要加上 \(l\sim mid\) 到 \(mid+1\sim r\) 互相的贡献)所以我们这里将 \(l\sim mid\) 标记成一种颜色再将 \(mid+1\sim r\) 标记成另一种颜色即可,然后我们在对于第 \(2\) 维进行排序再去算第 \(3\) 维即可。
bool cmpb(node a,node b) {
if(a.b!=b.b) return a.b<b.b;
if(a.c!=b.c) return a.c<b.c;
if(a.d!=b.d) return a.d<b.d;
return a.a<b.a;
}
void cdq(int l,int r) {
if(l==r) return ;
int mid=l+r>>1;
cdq(l,mid);
rep(i,l,r) pb[i]=s[i],pb[i].f=(i<=mid?1:2);
sort(pb+l,pb+r+1,cmpb);
cdq2(l,r);
cdq(mid+1,r);
}
这里我们按照三位排序的方法处理最后一维(树状数组)然后我们按照三维排序(分为 \(l\sim mid\) 和 \(mid+1\sim r\) 分别排序,因为需要保证第 \(2\) 维的顺序)的方法先将第三维排序再用双指针去看,如果一个在 \(l\sim mid\) 的值被标记为了在 \(L\sim Mid\)(这里表示再上面的标记中标记为了 \(1\)) 中 ,就将它的贡献加入树状数组,然后如果遍历到了一个 \(mid+1\sim r\) 的一个的标记为 \(2\) 就可以取最大值,只需要用树状数组处理出最大值即可。
void cdq2(int l,int r) {
if(l==r) return ;
int mid=l+r>>1;
cdq2(l,mid);
rep(i,l,r) pc[i]=pb[i];
sort(pc+l,pc+1+mid,cmpc);
sort(pc+mid+1,pc+1+r,cmpc);
int j=l;
for(int i=mid+1;i<=r;i++) {
while(pc[i].c>=pc[j].c&&j<=mid) {
if(pc[j].f==1) add(pc[j].d,f[pc[j].id]);
j++;
}
if(pc[i].f==2) f[pc[i].id]=max(f[pc[i].id],Ans(pc[i].d)+pc[i].e);
}
rep(i,l,mid) if(pc[i].f==1) clean(pc[i].d);
cdq2(mid+1,r);
}
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i,x,y) for(register int i=x;i<=y;i++)
#define rep1(i,x,y) for(register int i=x;i>=y;--i)
#define in(x) scanf("%lld",&x)
#define fire signed
#define il inline
il void print(int x) {
if(x<0) putchar('-'),x=-x;
if(x>=10) print(x/10);
putchar(x%10+'0');
}
int T;
int n,tot;
const int N=5e4+10,M=2e5+10;
struct node{
int a,b,c,d,e;
int f,id;
}p[N],s[N],pb[N],pc[N];
il bool cmpa(node a,node b) {
if(a.a!=b.a) return a.a<b.a;
if(a.b!=b.b) return a.b<b.b;
if(a.c!=b.c) return a.c<b.c;
return a.d<b.d;
}
bool cmpb(node a,node b) {
if(a.b!=b.b) return a.b<b.b;
if(a.c!=b.c) return a.c<b.c;
if(a.d!=b.d) return a.d<b.d;
return a.a<b.a;
}
bool cmpc(node a,node b) {
if(a.c!=b.c) return a.c<b.c;
if(a.d!=b.d) return a.d<b.d;
if(a.a!=b.a) return a.a<b.a;
return a.b<b.b;
}
int f[N];
int tr[M];
int idx;
int lowbit(int x) {
return x&-x;
}
void add(int x,int k) {
for(;x<=idx;x+=lowbit(x)) tr[x]=max(tr[x],k);
}
int Ans(int x) {
int res=-INT_MAX;
for(;x;x-=lowbit(x)) res=max(res,tr[x]);
return res;
}
void clean(int x) {
for(;x<=idx;x+=lowbit(x)) tr[x]=-1000100000000000;
}
bool cmp(node a,node b) {
return a.d<b.d;
}
unordered_map<int,int>mp;
int getd(int x) {
if(!mp[x]) mp[x]=++idx;
return mp[x];
}
void cdq2(int l,int r) {
if(l==r) return ;
int mid=l+r>>1;
cdq2(l,mid);
rep(i,l,r) pc[i]=pb[i];
sort(pc+l,pc+1+mid,cmpc);
sort(pc+mid+1,pc+1+r,cmpc);
int j=l;
for(int i=mid+1;i<=r;i++) {
while(pc[i].c>=pc[j].c&&j<=mid) {
if(pc[j].f==1) add(pc[j].d,f[pc[j].id]);
j++;
}
if(pc[i].f==2) f[pc[i].id]=max(f[pc[i].id],Ans(pc[i].d)+pc[i].e);
}
rep(i,l,mid) if(pc[i].f==1) clean(pc[i].d);
cdq2(mid+1,r);
}
void cdq(int l,int r) {
if(l==r) return ;
int mid=l+r>>1;
cdq(l,mid);
rep(i,l,r) pb[i]=s[i],pb[i].f=(i<=mid?1:2);
sort(pb+l,pb+r+1,cmpb);
cdq2(l,r);
cdq(mid+1,r);
}
void solve() {
in(n);
int ans=-INT_MAX;
rep(i,1,n) cin>>p[i].a>>p[i].b>>p[i].c>>p[i].d>>p[i].e,ans=max(ans,p[i].e);
sort(p+1,p+1+n,cmp);
rep(i,1,n) p[i].d=getd(p[i].d);
sort(p+1,p+1+n,cmpa);
int sum=false;
rep(i,1,n) {
sum+=p[i].e;
if(p[i].a!=p[i+1].a||p[i].b!=p[i+1].b||p[i].c!=p[i+1].c||p[i].d!=p[i+1].d) {
s[++tot]={p[i].a,p[i].b,p[i].c,p[i].d,sum,0,tot};
sum=false;
}
}
rep(i,1,n) tr[i]=-1000100000000000;
n=tot;
rep(i,1,n) f[i]=s[i].e;
cdq(1,n);
rep(i,1,n) ans=max(ans,f[i]);
printf("%lld",ans);
return;
}
fire main() {
T=1;
while(T--) {
solve();
}
return false;
}

浙公网安备 33010602011771号