小红书7.23提前批笔试2,3题
题目比较套路,好久没写题解了,写一下吧~
第二题:
第二题思路比较清晰,由于区间不重叠,直接给区间排个序,然后枚举每一个区间右端点作为最后选取的线段边界,二分左端点即可。
#include <bits/stdc++.h>
#include <numeric>
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define PII pair<long long, long long>
#define ll long long
#define x first
#define y second
#define mod 998244353
using namespace std;
inline ll gcd(ll a, ll b)
{
if (b)
{
return gcd(b, a % b);
}
return a;
}
inline ll qpow(ll a, ll b, ll p)
{
ll ans = 1;
a = (a % p + p) % p;
for (; b; b >>= 1)
{
if (b & 1)
ans = (a * ans) % p;
a = (a * a) % p;
}
return ans;
}
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
int r = exgcd(b, a % b, x, y);
int tmp = y;
y = x - a / b * y;
x = tmp;
return r;
}
// [0,n] 截取k
// 一共有m个区间
bool cmp(const PII& p1,const PII& p2){
return p1.second < p2.second;
}
ll n,m,k;
void solve()
{
cin >> n >> m >> k;
vector<PII> edges;
for(int i=1;i<=m;++i){
ll l1,r1;
cin >> l1 >> r1;
edges.push_back({l1,r1});
}
sort(edges.begin(),edges.end(),cmp);
edges.insert(edges.begin(),{-1e9,-1e9});
vector<ll> pre(m + 1,0);
for(int i=1;i<=m;++i){
pre[i] = pre[i-1] + edges[i].second - edges[i].first;
}
ll ans = 0;
for(int i=1;i<=m;++i){
ll target = edges[i].second - k;
int l = 1,r = i;
while(l < r){
int mid = (l + r) >> 1;
if(edges[mid].first >= target){
r = mid;
}
else l = mid + 1;
}
if(edges[l].first >= target){
ans = max(ans,pre[i] - pre[l-1] + max(edges[l-1].second - target,0ll));
}else{
ans = max(ans,pre[i]);
}
}
cout << ans << endl;
}
int main()
{
IOS;
int _ = 1;
while (_--)
{
solve();
}
return 0;
}
第三题:
第三题的话由于只多一个是否修改x的状态,不妨定义为f[i][0/1]为前i个元素是否修改过的最大子数组和,转移方程的话见代码:
#include <bits/stdc++.h>
#include <numeric>
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
#define PII pair<int, int>
#define ll long long
#define x first
#define y second
#define mod 998244353
using namespace std;
inline ll gcd(ll a, ll b)
{
if (b)
{
return gcd(b, a % b);
}
return a;
}
inline ll qpow(ll a, ll b, ll p)
{
ll ans = 1;
a = (a % p + p) % p;
for (; b; b >>= 1)
{
if (b & 1)
ans = (a * ans) % p;
a = (a * a) % p;
}
return ans;
}
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
int r = exgcd(b, a % b, x, y);
int tmp = y;
y = x - a / b * y;
x = tmp;
return r;
}
// 200000
const int N = 200010;
int a[N];
ll f[N][2]; // 0/1表示是否修改过了
int n,x;
void solve()
{
cin >> n >> x;
ll ans = -1e18;
for(int i=1;i<=n;++i){
cin >> a[i];
}
for(int i=0;i<=n;++i){
f[i][0] = f[i][1] = -1e18;
}
f[0][0] = 0;
for(int i=1;i<=n;++i){
f[i][0] = max(f[i][0],f[i-1][0] + a[i]);
f[i][0] = max(f[i][0],1ll * a[i]); // 从头取
f[i][1] = max(f[i][1],f[i-1][1] + a[i]);
f[i][1] = max(f[i][1],f[i-1][0] + x);
f[i][1] = max(f[i][1],1ll * x);
ans = max(ans,max(f[i][0],f[i][1]));
}
cout << ans << endl;
}
int main()
{
IOS;
int _;
cin >> _;
while (_--)
{
solve();
}
return 0;
}
查看16道真题和解析