前言
- 主要题解参考来源
- bilibili牛客竞赛官方讲解
D - 小A的线段(easy version)
思路:
- 用暴力即可通过
- 如——状态压缩
以下是代码部分
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10, mod = 998244353;
int vis[N];
vector<pair<int, int> > v;
bool check(int n)
{
for(int i = 1; i <= n; i ++)
if(vis[i] < 2)
return false;
return true;
}
void solve()
{
int n, m;
cin >> n >> m;
int pow_2 = 1 << m;
for(int i = 1; i <= m; i ++)
{
int st, cd;
cin >> st >> cd;
v.emplace_back(st, cd);
}
int sum = 0;
for(int i = 0; i < pow_2; i ++)
{
int k = i;
for(int kl = 1; kl <= n; kl ++) vis[kl] = 0;
for(auto it : v)
{
if(k % 2)
for(int jl = it.first; jl <= it.second; jl ++)
vis[jl] ++;
k /= 2;
}
if(check(n))
sum ++, sum %= mod;
}
cout << sum << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t = 1;
//cin >> t;
while(t --)
solve();
return 0;
}
E - 小A的任务
思路:
- 优先队列即可
以下是代码部分
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10;
ll a[N], b[N];
void solve()
{
//输入
int n, q, k;
cin >> n >> q;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) cin >> b[i];
while(q --)
{
cin >> k;
priority_queue<ll> prio;
ll ans = 1e17, sum = 0, n_sum = 0;
//找到数量为k的时候的b的最小状态
for(int i = 1; i <= n; i ++)
{
sum += a[i];
prio.push(b[i]);
n_sum += b[i];
if(prio.size() > k)
n_sum -= prio.top(), prio.pop();
if(prio.size() == k)
ans = min(ans, sum + n_sum);
}
cout << ans << '\n';
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}
F - 小A的线段(hard version)
移步——出题人题解
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 10, mod = 998244353;
int dp[401][401][401];
void add(int& ret, int x)
{
ret += x;
if(ret >= mod) ret -= mod;
}
void solve()
{
int n, m;
cin >> n >> m;
vector<int> v;
vector<int> s(m + 1), t(m + 1);
//离散化处理
for(int i = 1; i <= m; i ++)
{
cin >> s[i] >> t[i];
//统一下标
s[i] --;
//存储左端点
v.push_back(s[i]);
//存储右端点
v.push_back(t[i]);
}
//存储断点0, n
v.push_back(n), v.push_back(0);
//从小到大排序
sort(v.begin(), v.end());
//去重
v.resize(unique(v.begin(), v.end()) - v.begin());
n = (int)v.size();
vector<pair<int, int> > a(m + 1);
for(int i = 1; i <= m; i ++)
{
//二分查找第一个小于等于s[i], 并存入位置
s[i] = lower_bound(v.begin(), v.end(), s[i]) - v.begin();
//二分查找第一个小于等于t[i], 并存入位置
t[i] = lower_bound(v.begin(), v.end(), t[i]) - v.begin();
//存入到a[i]当中
a[i] = {s[i], t[i]};
}
//从小到大排序,并跳过下标为1的时候
sort(a.begin() + 1, a.end());
//初始化
dp[0][0][0] = 1;
for(int k = 1; k <= m; k ++)
for(int i = 0; i < n; i ++)
for(int j = i; j < n; j ++)
{
if(dp[k - 1][i][j] == 0) continue;
add(dp[k][i][j], dp[k - 1][i][j]);
if(a[k].first <= i)
add(dp[k][max(i, min(j, a[k].second))][max(j, a[k].second)], dp[k - 1][i][j]);
}
cout << dp[m][n - 1][n - 1] << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
solve();
return 0;
}