P3364 Cool loves touli 题解

题目传送门

前置知识

将动态问题转化为静态问题 | 树状数组

解法

先将英雄按 \(\{ l \}\) 升序排序,从而减少一维偏序。

\(f_{i}\) 表示以 \(i\) 结尾的最长合法序列长度,状态转移方程为 \(f_{i}=\max\limits_{j=1}^{i-1}\{ [a_{j} \le s_{i} \land w_{j} \le a_{i}] \times f_{j}+1 \}\)

然后就是 CDQ 分治优化 DP 的板子题了。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define ull unsigned long long
#define sort stable_sort 
#define endl '\n'
struct node
{
	int l,s,w,a,id;
}q[100010];
struct BIT
{
	int c[100000010];
	int lowbit(int x)
	{
		return (x&(-x));
	}
	void add(int n,int x,int val)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		{
			c[i]=max(c[i],val);
		}
	}
	int getsum(int x)
	{
		int ans=0;
		for(int i=x;i>=1;i-=lowbit(i))
		{
			ans=max(ans,c[i]);
		}
		return ans;
	}
	void del(int n,int x)
	{
		for(int i=x;i<=n;i+=lowbit(i))
		{
			c[i]=0;
		}
	}
}T;
int f[100010];
bool cmpl(node a,node b)
{
	return a.l<b.l;
}
bool cmps(node a,node b)
{
	return a.s<b.s;
}
bool cmpa(node a,node b)
{
	return a.a<b.a;
}
bool cmpid(node a,node b)
{
	return a.id<b.id;
}
void cdq(int l,int r,int k)
{
	if(l==r)
	{
		return;
	}
	int mid=(l+r)/2,x,y;
	cdq(l,mid,k);
	sort(q+l,q+mid+1,cmpa);
	sort(q+mid+1,q+r+1,cmps);
	for(x=l,y=mid+1;y<=r;y++)
	{
		for(;q[x].a<=q[y].s&&x<=mid;x++)
		{
			T.add(k,q[x].w,f[q[x].id]);
		}
		f[q[y].id]=max(f[q[y].id],T.getsum(q[y].a)+1);
	}
	x--;
	for(int i=l;i<=x;i++)
	{
		T.del(k,q[i].w);
	}
	sort(q+mid+1,q+r+1,cmpid);
	cdq(mid+1,r,k);
}
int main()
{
	int n,ans=0,i;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		cin>>q[i].l>>q[i].s>>q[i].w>>q[i].a;
		f[i]=1;
	}
	sort(q+1,q+1+n,cmpl);
	for(i=1;i<=n;i++)
	{
		q[i].id=i;
	}
	cdq(1,n,100000000);
	for(i=1;i<=n;i++)
	{
		ans=max(ans,f[i]);
	}
	cout<<ans<<endl;
	return 0;
}

后记

多倍经验: luogu P4093 [HEOI2016/TJOI2016] 序列

posted @ 2024-09-30 08:10  hzoi_Shadow  阅读(16)  评论(0编辑  收藏  举报
扩大
缩小