23ccpc桂林M

这篇文章讨论了解决Codeforces问题中关于计算给定区间内点对交换贡献的问题,使用C++编程语言实现了一个函数,通过区间查询和二分查找找到满足特定条件的最大连续子序列长度。
摘要由CSDN通过智能技术生成

Problem - M - Codeforces

using ll = long long;
#define f first
#define s second
using pii = std::pair<ll, ll>;
void solve() {
	ll n,left=1,right=1;
	std::cin >> n;
	std::vector <pii> a(n);
	//输入并求a和b当中的最大值
	for (int i = 0; i < n; i++) {
		std::cin >> a[i].f >> a[i].s;
		right = std::max(right, a[i].f+1);
		right = std::max(right, a[i].s+1);
	}
	auto check = [&](ll mid)->bool {
		ll ans = 0, cnt = 0, cur = 0;
		std::vector<ll>b(n);
		//计算一个点的贡献
		//首先a[i].s<mid=0,a[i].s>=mid=1,同理a[i].f<mid=0,a[i].f>=mid=1
		//1.如果a<mid而b>=mid,实际来看交换肯定为正贡献,计算来看1-0=1为正
		//2.如果a<mid且b<mid或a>=mid且b>=mid交不交换都没影响,贡献为0,计算来看0-0或1-1=0;
		//3.如果a>=mid且b<mid,显然计算来看=-1;
		for (int i = 0; i < n; i++)b[i] = (a[i].s >= mid) - (a[i].f >= mid);
		//连续子序列最大权值
		for (int i = 0; i < n; i++) {
			//原本就大于mid的值
			if (a[i].f >= mid) {
				cnt++;
			}
			//对于原本就大于mid的点,b[i]要么为-1,要么为0
			//假设原本大于mid的点为k
			//00k0k00k
			//0101-1110
			//所以ans+cnt不会产生覆盖区域,即不会产生a[i[.f>=mid=1切b[i]=1的情况
			//即不会一个点加两个1,但这不影响它是一个连续的子段前面的子段不为0时-1也会添加到子段里
			cur = std::max(0LL, cur)+b[i];
			ans = std::max(ans, cur);
		}
		//12345,(5+1)/2=3,1234,(4+1)/2=2;有两个比mid大的就刚好到3满足.
		return ans + cnt >= (n + 1) / 2;
	};
	while (left + 1 < right) {
		ll mid = (left + right) >> 1;
		//return true说明满足,可以寻找更大的mid,即left是>=,right是<不满足,
		//left最后是最大的满足条件的值,right是最小的不满足条件的值
		if (check(mid))left = mid;
		else right = mid;
	}
	std::cout << left << '\n';
}
int main() {
	std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
	solve();
	return 0;
}

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值