把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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);
}
posted @ 2021-01-14 19:58  275307894a  阅读(116)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end