2023大厂真题提交网址(含题解):
www.CodeFun2000.com(http://101.43.147.120/)
最近我们一直在将收集到的机试真题制作数据并搬运到自己的OJ上,供大家免费练习,体会真题难度。现在OJ已录入50+道2023年最新大厂真题,同时在不断的更新。同时,可以关注"塔子哥学算法"公众号获得每道题的题解。
题目大意:
给 n n n个线段.假设选择 k k k个线段,它们的交集长度为 s s s.要求最大化 m i n ( k , s ) min(k,s) min(k,s).
n , L i , R i ≤ 3 e 5 n , L_i,R_i\leq 3e5 n,Li,Ri≤3e5
题目思路:
首先想的是三分选择的 k k k个线段。求最大的交集。因为 s s s随着 k k k增大而减小。所以 m i n ( k , s ) min(k,s) min(k,s)最大值存在于它们值接近的地方。
但是无法实现求最大交集.所以没写出来。
正解: 枚举交集长度
s
s
s.
枚举左端点
L
L
L.右端点
R
R
R越大,
s
s
s越大。但
k
k
k越小。
所以这个时候可以三分.但是这里提供一个二分的思路:
m i n ( a , b ) min(a,b) min(a,b), a , b a,b a,b成反比时。那么我们可以求最大的 a a a使得 a ≤ b a \leq b a≤b.
然后就是已知
L
,
s
L,s
L,s,求
k
k
k:求有多少个
l
i
,
r
i
l_i,r_i
li,ri使得
l
i
≤
L
&
&
r
i
≤
L
+
s
−
1
l_i \leq L\ \&\& \ r_i \leq L + s - 1
li≤L && ri≤L+s−1
这个显然可以用树状数组计算贡献。
AC代码:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
vector<int> a[maxn];
int n , m , sum[maxn];
int lowbit(int x){return x & -x;}
void add(int x,int c){while(x<=n){sum[x] += c;x += lowbit(x);}}
int ask(int x){int ans=0;while(x){ans+=sum[x];x-=lowbit(x);}return ans;}
int main()
{
ios::sync_with_stdio(false);
cin >> n >> m;
for (int i = 1 ; i <= m ; i++){
int x , y; cin >> x >> y;
a[x].push_back(y);
}
int ans = 0;
for (int i = 1 ; i <= n ; i++){
for (auto & g : a[i]) add(g , 1);
int l = i , r = n , mid;
while(l <= r)
{
mid = l + r >> 1;
int val = ask(n) - ask(mid - 1);
if (mid - i + 1 <= val) l = mid + 1;
else r = mid - 1;
}
ans = max (ans , r - i + 1);
}
cout << ans << endl;
return 0;
}