P6390 [COCI2007-2008#4] POKLON 题解

感谢 @Celestial Cyan 大神对我的骚扰帮助。

分析

一眼 DP。

对于求最大满足条件区间数,我们定义状态函数 fi 表示在第 1i 个区间中选择,且必选第 i 个区间能够得到的最大长度。有转移方程:fi=max{f[j]|ajaibjbi}+1

可以得到 50 分的 O(n2) 的代码:

for(re int i=1;i<=n;++i){
	f[i]=1;
	for(re int j=1;j<i;++j){
		if(a[i].l>=a[j].l&&a[j].r>=a[i].r){
			if(f[j]+1>f[i]) f[i]=f[j]+1,nxt[i]=j;
		}
	}
}

考虑优化 fi 的转移。这个代码与 LIS 模板几乎一致,所以很显然的也可以使用树状数组优化。因为我们需要记录方案,所以树状数组存 2 维:价值与该价值对应的下标。

我们将 a,b 用一个结构体存放,按第一维从小到大排序。可以得到:对于每一个 i,都有 1ji,ajai。这样我们就消除了区间左端点的影响。剩下的就用树状数组查询 bi 的最大的 fj 的值与其下标。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register
#define il inline
#define PII pair<int,int>
#define x first
#define y second
const int N=1e5+10,MAXN=1e6+10;
int n;
PII f[N],tr[MAXN];
struct node{
	int l,r;
}a[N];
stack<int> st;
int id,maxx;
il bool cmp(node a,node b){return (a.l!=b.l)?(a.l<b.l):(a.r>b.r);}
il void insert(int x,int y,int id){
	while(x){
		if(tr[x].x<y) tr[x].x=y,tr[x].y=id;
		x-=x&(-x);
	}
	return ;
}
il PII query(int x){
	PII ans;ans={0,0};
	while(x<=MAXN){
		if(ans.x<tr[x].x) ans.x=tr[x].x,ans.y=tr[x].y;
		x+=x&(-x);
	}
	ans.x++;return ans;
}
il void read(){
	scanf("%lld",&n);
	for(re int i=1;i<=n;++i) scanf("%lld%lld",&a[i].l,&a[i].r);
	sort(a+1,a+n+1,cmp);
	return ;
}
il void solve(){
	for(re int i=1;i<=n;++i) f[i]=query(a[i].r),insert(a[i].r,f[i].x,i);
	for(re int i=1;i<=n;++i){
		if(maxx<f[i].x) maxx=f[i].x,id=i;
	}
	while(id!=0) st.push(id),id=f[id].y;
	return ;
}
il void print(){
	printf("%lld\n",maxx);
	while(!st.empty()){
		int now=st.top();st.pop();
		printf("%lld %lld\n",a[now].l,a[now].r);
	}
	return ;
}
signed main(){
	read(),solve(),print();
	return 0;
}
posted @   harmis_yz  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示