luogu P5621 [DBOI2019]德丽莎世界第一可爱
题面传送门
这道题直接\(cdq\)套\(cdq\)即可。
但是问题是怎么套呢?
考虑\(cdq\)维护查询和修改的时候,我们对于修改标记\(1\),查询标记\(0\),所以我们可以在进入下一层\(cdq\)前将左半边设成修改,而右半边设成查询即可。
还有这道题卡常。
代码实现:
#include<cstdio>
#include<algorithm>
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int n,m,k,now[100039],tots[100039];
long long f[100039],dp[100039],ans;
struct yyy{int a,b,c,d;int w;int id,flag,idea;}s[100039],b[100039],d[100039];
inline bool cmp1(yyy x,yyy y){return x.a==y.a?(x.b==y.b?(x.c==y.c?x.d<y.d:x.c<y.c):x.b<y.b):(x.a<y.a);}
inline bool cmp2(yyy x,yyy y){return x.b==y.b?(x.c==y.c?x.d<y.d:x.c<y.c):x.b<y.b;}
inline bool cmp3(yyy x,yyy y){return x.c==y.c?x.d<y.d:x.c<y.c;}
inline void get(int x,long long y){while(x<=n) f[x]=max(f[x],y),x+=x&-x;}
inline long long find(int x){long long ans=0;while(x) ans=max(f[x],ans),x-=x&-x;return ans;}
inline void clear(int x){while(x<=n&&f[x]) f[x]=0,x+=x&-x;}
inline void solve2(int x,int y){
if(x==y) return ;
register int m=x+y>>1,i,l=x,now;solve2(x,m);
sort(b+x,b+m+1,cmp3);sort(b+m+1,b+y+1,cmp3);
for(i=m+1;i<=y;i++){
while(l<=m&&b[l].c<=b[i].c){
if(!b[l].flag)get(b[l].d,dp[b[l].id]);
l++;
}
if(b[i].flag)now=find(b[i].d),dp[b[i].id]=max(dp[b[i].id],now+b[i].w);
}
for(i=x;i<l;i++) if(!b[i].flag) clear(b[i].d);
for(i=m+1;i<=y;i++) d[b[i].idea]=b[i];
for(i=m+1;i<=y;i++) b[i]=d[i];
solve2(m+1,y);
}
inline void solve(int x,int y){
if(y==x) return;
register int m=x+y>>1,i;
solve(x,m);
for(i=x;i<=y;i++)b[i]=s[i];
for(i=m+1;i<=y;i++) b[i].flag=1;
sort(b+x,b+y+1,cmp2);for(i=x;i<=y;i++) b[i].idea=i;solve2(x,y);
solve(m+1,y);
}
inline int ls(int x){
int l=0,r=n+1,mid;
while(l+1<r){
mid=l+r>>1;
if(now[mid]<x) l=mid;
else r=mid;
}
return tots[r];
}
static char buf[1000000],*p1=buf,*p2=buf;
#define getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++
inline void read(int &x){
int f=1;x=0;char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
x*=f;
}
int main(){
freopen("1.in","r",stdin);
register int i;
read(n);
for(i=1;i<=n;i++)read(s[i].a),read(s[i].b),read(s[i].c),read(s[i].d),read(s[i].w),dp[i]=s[i].w,now[i]=s[i].d,s[i].id=i;
sort(now+1,now+n+1);now[0]=now[1]-1;
for(i=1;i<=n;i++)tots[i]=tots[i-1]+(now[i-1]!=now[i]);
for(i=1;i<=n;i++) s[i].d=ls(s[i].d);
sort(s+1,s+n+1,cmp1);
solve(1,n);
for(i=1;i<=n;i++) ans=max(ans,dp[i]);
printf("%lld\n",ans);
}