loj #2729. 「JOISC 2016 Day 1」俄罗斯套娃

loj #2729. 「JOISC 2016 Day 1」俄罗斯套娃
先丢个官方题解
官方题解讲得比较详细
这题的关键其实就是把最小路径覆盖转换为最长不上升子序列
然后我们就可以先把询问和原来的点离线一下在离散化
按照A从大到小排序,然后就转换为了求最长不下降子序列问题
直接树状数组维护前缀最大值即可
看代码很容易明白的
code:

#include<bits/stdc++.h>
#define N 1000005
#define lowbit(x) (x & -x)
using namespace std;
struct A{
	int x, y, id;
}a[N];
int cmp(A x, A y){
	if(x.x != y.x) return x.x > y.x;
	if(x.y != y.y) return x.y < y.y;
	return x.id < y.id;//注意这里一定要按照id排序,想想为啥
}
int tree[N];
void update(int x, int y){//树状数组维护前缀最大值
	for(; x < N; x += lowbit(x)) tree[x] = max(tree[x], y);
}
int query(int x){
	int ret = 0;
	for(; x; x -= lowbit(x)) ret = max(ret, tree[x]);
	return ret;
}
int n, q, b[N], ANS[N];
int main(){
	scanf("%d%d", &n, &q);
	for(int i = 1; i <= n; i ++) scanf("%d%d", &a[i].x, &a[i].y), b[i] = a[i].y;
	for(int i = 1; i <= q; i ++) scanf("%d%d", &a[i + n].x, &a[i + n].y), b[i + n] = a[i + n].y, a[i + n].id = i;//把问题离线一下
	sort(b + 1, b + 1 + n + q);//排序用于离散化
	sort(a + 1, a + 1 + n + q, cmp);//把询问排序
	for(int i = 1; i <= n + q; i ++){
		int pos = lower_bound(b + 1, b + 1 + n + q, a[i].y) - b;//离散化
		if(a[i].id) ANS[a[i].id] = query(pos);//求最长不下降子序列
		else update(pos, query(pos) + 1);//如果是DAG上的点就加上去
	}
	for(int i = 1; i <= q; i ++) printf("%d\n", ANS[i]);//输出
	return 0;
}

离线大法吼哇

坑点

就是多关键字排序那里一定要注意id也要参与排序,不然会贡献不充分

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值