【LGR-250】洛谷 NOIP 2025 模拟赛
【LGR-250】洛谷 NOIP 2025 模拟赛
比赛链接:【LGR-250】洛谷 NOIP 2025 模拟赛
A.mexdnc
原题链接:缺零分治 mexdnc
分析
考场上推出神秘性质——只能从$0$到$mex$取数,而出入的$m$也必须在这个最大和的范围,从大到小取从贪心角度解释是优的,找到第一个大于等于的前缀和即可?好了,思路如此,看看代码写成啥了——$RE\times2,WA\times3,AC\times2,MLE\times 13$,那还说啥?HE一篇题解。
正解
#include<bits/stdc++.h>
using namespace std;
int T, n, q;
struct node{
long long a, b;
}inp[100010];
long long sum[100010], cnt_sum[100010];
long long m;
int main(){
// freopen("mexdnc.in","r",stdin);
// freopen("mexdnc.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> T;
while (T--){
cin >> n >> q;
for (int i = 1; i <= n; i++)
cin >> inp[i].a >> inp[i].b;
inp[0].b = 0x3f3f3f3f3f3f3f3f;
long long mex = 0;
for (int i = 1; i <= n; i++){
if (mex == inp[i].a){
mex++;
inp[i].b = min(inp[i - 1].b, inp[i].b);
}
else
break;
}
n = mex;
inp[n + 1].b = 0;
for (int i = 1; i <= n; i++){
inp[i].a = i;
inp[i].b -= inp[i + 1].b;
}
reverse(inp + 1, inp + 1 + n);
for (int i = 1; i <= n; i++){
sum[i] = sum[i - 1] + inp[i].a * inp[i].b;
}
for (int i = 1; i <= n; i++){
cnt_sum[i] = cnt_sum[i - 1] + inp[i].b;
}
while (q--){
cin >> m;
if (n == 0){
if (m == 0)
cout << 1 << '\n';
else
cout << -1 << '\n';
continue;
}
if (m == 0 || m > sum[n]){
cout << -1 << '\n';
continue;
}
if (m == sum[n]){
cout << cnt_sum[n] << '\n';
continue;
}
if (m < inp[1].a){
cout << 2 << '\n';
continue;
}
int l = 1, r = n + 1;
while (l < r){
int mid = (l + r) >> 1;
if (sum[mid] <= m)
l = mid + 1;
else
r = mid;
}
long long ans = cnt_sum[l - 1] + (m - sum[l - 1] + inp[l].a - 1) / inp[l].a;
cout << ans << '\n';
}
memset(inp, 0, sizeof(inp));
memset(sum, 0, sizeof(sum));
memset(cnt_sum, 0, sizeof(cnt_sum));
}
}
B.guess
原题链接:猜数游戏 guess
分析
好的,其实是数轴,比较类似于交互?
08点55分
是不是先用性价比最高的从$[1,n]$跑一遍,进一步缩小范围然后再跑再跑?感觉很假,我去问问。
08点57分
啥?$DP?$那假了,盯一下状态……
09点03分
呃,我理解对题目了吗?好吧,就是说来到区间中点,我们一定知道目标在区间哪一部分,难道走$logn$步一定优吗?也不一定,因为花费没有任何规律,那么就把在区间左部还是右部记入状态?但是,如果设成类似区间$DP$的形式显然时间跑不下。所以要优化掉一维,
设$f_{i,0/1}$表示长度为$i$的区间从左/右转移的最大花费,发现第二维没用,直接省略掉。那么,直接设$f_i$表示长度为$i$的区间最大花费,转移即为
$f_i=\min\limits_{j\in [1,i]}(cost_j+\min(f_{j},f_{i-j}))$
真的没抄题解,纯抄$mhh$的!
考虑如何获得到达某个点的$cost_j$……背包被Hack了,贪心是较为正确的。
09点20分
呃,写完了转移方程。贪心过程居然形如最短路状物!!!呃,这个不建图的Trick我似乎并不会,开始HE题解。
10点21分
终于写出来正解了/(ㄒoㄒ)/~~
正解
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 10005, M = 1005;
const long long INF = 0x3f3f3f3f3f3f3f3f;
int c, T;
int n, m, maxv;
struct node{
int a, b;
}inp[M];
long long cost[N << 1], f[N];
priority_queue<pair<long long, int>, vector<pair<long long, int>>, greater<pair<long long, int>>> q;
void dijkstra(){
for (int i = -maxv; i <= maxv; i++)
cost[i + N] = INF;
cost[N] = 0;
q.push({0, 0});
while (!q.empty()){
auto tmp = q.top();
q.pop();
int w = tmp.first, u = tmp.second;
if (w != cost[u + N])
continue;
for (int i = 1; i <= m; i++){
if (u + inp[i].a <= maxv){
int v = u + inp[i].a;
if (cost[u + N] + inp[i].b < cost[v + N]){
cost[v + N] = cost[u + N] + inp[i].b;
q.push({cost[v + N], v});
}
}
if (u - inp[i].a >= -maxv){
int v = u - inp[i].a;
if (cost[u + N] + inp[i].b < cost[v + N]){
cost[v + N] = cost[u + N] + inp[i].b;
q.push({cost[v + N], v});
}
}
}
}
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> c >> T;
while (T--){
maxv = 0;
cin >> n >> m;
for (int i = 1; i <= m; i++){
cin >> inp[i].a;
maxv = max(maxv, inp[i].a);
}
for (int i = 1; i <= m; i++)
cin >> inp[i].b;
dijkstra();
for (int i = 0; i <= n; i++)
f[i] = INF;
f[1] = 0;
for (int i = 2; i <= n; i++){
for (int j = 1; j <= maxv && j <= i; j++){
f[i] = min(f[i], max(f[j], f[i - j]) + cost[j + N]);
}
}
if (f[n] != INF)
cout << f[n] << '\n';
else
cout << -1 << '\n';
}
return 0;
}
由于存在负半轴,注意开两倍。
C.tree
原题链接:树上求值 tree
分析
这个就开始阴了,毕竟是紫题,我认为到11:30前写出来就很好了。
我决定不补了,或是因为浮躁,但是我并未真正看懂题目,再见。
D.miss
原题链接:夜里亦始终想念着你 miss
分析
我甚至认为这题更可补。
呃,场上 出现了幻觉,认为甚至$T4$更简单,显然不。感觉是比较复杂的容斥+组合数?
我需要题解。
好吧,似乎也不可补……撤了。
posted on 2025-11-18 20:50 hetao1733837 阅读(22) 评论(0) 收藏 举报
浙公网安备 33010602011771号