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;
}
23ccpc桂林M
于 2024-03-17 22:54:37 首次发布
![](https://img-home.csdnimg.cn/images/20240711042549.png)