温澈滢的狗狗(二分)

LINK
题目描述
众所周知,温澈滢在宿舍养了一排 n 只狗狗,每只狗狗都有一个颜色 cic_ici​ 。同时,它们只喜欢和不同颜色的狗狗玩,否则它们会觉得很单调无趣。

也就是说,如果第 i 只狗狗和第 j 只狗狗颜色不同,那么它们可以拥有亲密关系,它们亲密度可以表示成 ∣ i − j ∣ ∣ i − j ∣ ∣ i − j ∣ ∣i−j∣\mid i-j\mid∣i−j∣ ijijij,否则它们就不能建立亲密关系。

当 n 只狗狗颜色两两不同时,它们有 n ( n − 1 ) 2 n ( n − 1 ) 2 2 n ( n − 1 ) ​ n(n−1)2\frac{n(n-1)}{2}2n(n−1)​ n(n1)22n(n1)2n(n1)对亲密关系;当 n 只狗狗的颜色完全一致时,它们之间就不存在任何一对亲密关系。

我们把这么多对亲密关系取出来,以亲密度为第一关键词,编号较小的狗狗的编号为第二关键词,编号较大的狗狗的编号为第三关键词排序(三维都按照升序排序)。

现在温澈滢想知道第 k 对亲密关系是哪一对狗狗,当然,必要的时候你可以告诉温澈滢这些狗狗之间不存在这么多的亲密关系。
输入描述:

第一行输入两个数字 n 和 k 。

第二行给出 n 个数字,第 i 个数字 c i ​ ci​ ci 表示第 i 只狗狗的颜色。

输出描述:

如果存在第 k 对狗狗,请在一行内输出两只狗狗的编号,小的在前,中间用一个空格隔开。

否则输出 -1 。

思路

来自题解:
倘若我们知道了第k对亲密关系的亲密值是多少就好办了,显然可以二分, 那二分什么呢, 二分亲密度, 因为最终的排名就是按照亲密度升序排列, 我们只需找到当前的小于当前二分的亲密度的关系对数, 是不是大于k即可, 在查询小于k的亲密度关系对数是,可以用双指针, 维护一个差值为k的区间, 然后依次求出当前区间最左边中的元素与区间中所有元素的亲密度即可
这里借鉴别人的代码

#include <bits/stdc++.h>

using namespace std;
#define ll long long
const ll N = 2e5 + 10;
ll c[N], vis[N], n, k;

ll check(ll mid)
{
	for(ll i = 1; i <= n; i++) vis[i] = 0;
	for(ll i = 1; i <= mid + 1; i++) vis[c[i]] ++;
	ll ans = mid + 1 - vis[c[1]], len = mid + 1;
	for(ll l = 2, r = mid + 2; l < n; r ++, l ++)
	{
		vis[c[l - 1]] --;
		if(r <= n) vis[c[r]] ++;
		else len --;
		ans += len - vis[c[l]];
	}
	return ans;
}
int main()
{
	cin >> n >> k;
	for(ll i = 1; i <= n; i++) cin >> c[i];
	ll l = 1, r = n - 1, ans = 0;
	while(r >= l)
	{
		ll mid = l + r >> 1;
		if(check(mid) >= k)r = mid - 1, ans = mid;
		else l = mid + 1;
	}
	if(ans == 0)
	{
		cout << -1 << endl;
		return 0;
	}
	ll las = check(ans - 1);
	for(ll i = ans + 1; i <= n; i++)
	{
		if(c[i] == c[i - ans]) continue;
		if(++las == k)
		{

			cout << i - ans << " " << i << endl;
			return 0;
		}
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值