B - Dividing Subsequence(思维)

AtCoder Regular Contest 133

题意

给出两个长度为n的排列a, b(含n个数字,1~n每个数字只出现一次)。假设p,q分别为a,b的子序列,长度相同,且q中每个数字均是p中的倍数。( 1 ≤ n ≤ 2 e 5 1 \leq n \leq 2e5 1n2e5

思路

  • 将a,b中所有有倍数关系的数子的下标用pair存起来(大约有 N l n N NlnN NlnN )。然后对第一维按升序排列,第一维相同时,第二维按降序排列。此时,问题已经转化为,求pair的第二维中最长的严格上升子序列
  • 由于数据范围较大,只能用贪心+二分的方式求最长上升子序列。
  • 同时注意数组越界,调和级数求和为 N l n N NlnN NlnN的级别。 l n ( 2 e 5 ) ≈ 13 ln(2e5) ≈ 13 ln(2e5)13所以数组最小要开 2 e 5 × 13 ≈ 3 e 6 2e5 \times 13 ≈ 3e6 2e5×133e6
  • 算法时间复杂度: N l o g 2 N Nlog^2N Nlog2N
const int N = 2e5 + 7, M = 3e6 + 7;
int a[N], b[N];
pii s[M];

bool cmp(pii a, pii b)
{
	if (a.ft == b.ft) return a.sd > b.sd;
	return a.ft < b.ft;
}

int main()
{
	IOS;

	int n; cin >> n;
	for (int i = 1, x; i <= n; i++)
		cin >> x, a[x] = i;
	for (int i = 1, x; i <= n; i++)
		cin >> x, b[x] = i;

	int k = 0;
	for (int i = 1; i <= n; i++)
		for (int j = i; j <= n; j += i)
			s[k++] = { a[i], b[j] };

	sort(s, s + k, cmp);

	int ans = 0;
	vector<int>v;
	for (int i = 0; i < k; i++)
	{
		if (v.empty() || s[i].sd > v.back())
			v.push_back(s[i].sd);
		else
		{
			int idx = lower_bound(all(v), s[i].sd) - v.begin();
			v[idx] = s[i].sd;
		}
	}

	cout << sz(v) << endl;

	return 0;
	
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

to cling

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值