NOIP2025模拟赛29
T1 | T2 | T3 | T4 |
---|---|---|---|
\(\color{#FFC116} 普及/提高-\) | \(\color{#52C41A} 普及+/提高\) | \(\color {#3498DB} 提高+/省选-\) | \(\color{#9D3DCF} 省选/NOI-\) |
参赛网址:https://oj.33dai.cn/d/TYOI/contest/68a830bac5d9c2f14c2aa5f9
本场契合当前竞赛国际导向“灵活应用,注重思维”,知识点都在提高组范围内,请认真打比赛,赛后好好补题。
T1 打怪【NOIP2025模拟赛T1】
题目难度:\(\color{#FFC116} 普及/提高-\)
算法标签:贪心,其他,二分查找,NOISG
思路
首先,我们发现,将一只怪物打死有两种方式:
-
将一只怪物向左或向右移动到一个地雷然后引爆地雷
-
减少一只怪物的生命值到 0
所以考虑对于第 \(i\) 只怪,\(\forall i \in [1,n]\),如果他移动到旁边地雷的距离都大于将它在原地打死的花费,那么就将它在原地打死。
否则就将它移到旁边的地雷即可。
::::warning[警告]{open}
优先使用靠右的地雷
::::
AC Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=2e5+5;
const int inf=1e18;
int n,k;
int ans;
struct node{
int a,h;
friend bool operator < (const node &x,const node &y){
return x.a<y.a;
}
}a[maxn];
int x[maxn];
int vis[maxn];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>k;
for (int i=1;i<=n;i++) cin>>a[i].a>>a[i].h;
for (int i=1;i<=k;i++) cin>>x[i];
x[k+1]=-inf,x[k+2]=inf;
k+=2;
sort(x+1,x+k+1);
sort(a+1,a+n+1);
for (int i=1;i<=n;i++){
int nxt=lower_bound(x+1,x+k+1,a[i].a)-x;
if (x[nxt]==a[i].a){
ans++;
vis[nxt]=1;
}
}
for (int i=1;i<=n;i++){
int nxt=lower_bound(x+1,x+k+1,a[i].a)-x;
if (x[nxt]==a[i].a) continue;
int las=nxt-1;
int f=a[i].a-x[las]+(vis[las]==0);
int g=x[nxt]-a[i].a+(vis[nxt]==0);
int l=a[i].h;
if (min(f,g)>l) ans+=l;
else {
if (f>=g){
ans+=g;
vis[nxt]=1;
}
else {
ans+=f;
vis[las]=1;
}
}
}
cout<<ans;
return 0;
}
T2 弹珠游戏【NOIP2025模拟赛T2】
题目难度:\(\color{#52C41A} 普及+/提高\)
算法标签:贪心,动态规划,最大子段和
思路
题目要求的是:
无论 Bob 如何选择,都确保她 \(M\) 轮游戏不输。
那么我们就考虑最坏情况,所以 Bob 要最大化收益,则 Alice 猜奇数,Bob 就是用最大的偶数,如果没有偶数,就让 Alice 的收益最小。猜偶数的同理。
设 \(odd_i\) 是 Alice 猜奇数时,她的亏损(负数即为收益),\(even_i\) 同理。
even[i]=omax;
if (omax==0) even[i]=-emin;
odd[i]=emax;
if (emax==0) odd[i]=-omin;
Alice 为了不输,她肯定是亏损最小,取 \(\min(even_i,odd_i)\)。
然后求 \(\min(even_i,odd_i)\) 的后缀最大子段和,如果 \(f_1 \ge m\),答案为 -1。
否则应该枚举每一位:如果可以用 Even 则直接输出 Even,否则考虑 Odd。
AC Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=3e5+5;
const int inf=1e18;
int T;
int n,m,k;
int f[maxn];
int a[maxn][5];
int even[maxn],odd[maxn];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
// freopen("data_2.in","r",stdin);
// freopen("data.out","w",stdout);
cin>>T;
while (T--){
cin>>m>>n>>k;
for (int i=1;i<=n;i++){
int emin=inf,omin=inf;
int emax=0,omax=0;
for (int j=1;j<=k;j++){
cin>>a[i][j];
if ((a[i][j]&1)==0){
emin=min(emin,a[i][j]);
emax=max(emax,a[i][j]);
}
else{
omin=min(omin,a[i][j]);
omax=max(omax,a[i][j]);
}
}
even[i]=omax;
if (omax==0) even[i]=-emin;
odd[i]=emax;
if (emax==0) odd[i]=-omin;
}
f[n+1]=0;
for (int i=n;i>=1;i--) f[i]=max(f[i+1],0ll)+min(even[i],odd[i]);
if (f[1]>=m) cout<<-1<<"\n";
else {
for (int i=1;i<=n;i++){
if (f[i+1]+even[i]<m&&even[i]<m) cout<<"Even ",m-=even[i];
else cout<<"Odd ",m-=odd[i];
}
cout<<"\n";
}
}
return 0;
}
T3 兔子【NOIP2025模拟赛T3】
题目难度:\(\color {#3498DB} 提高+/省选-\)
算法标签:组合数学,差分,数据结构,树状数组,坐标旋转
思路
AC Code
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxn=5e5+5;
int n,m;
int x[maxn],y[maxn];
int nx[maxn],ny[maxn];
int tx[maxn],ty[maxn];
int bx[maxn],by[maxn];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for (int i=1;i<=n;i++){
cin>>x[i]>>y[i];
nx[i]=bx[i]=x[i]+y[i];
ny[i]=by[i]=x[i]-y[i];
}
sort(bx+1,bx+n+1);
sort(by+1,by+n+1);
for (int i=1;i<=n;i++){
nx[i]=lower_bound(bx+1,bx+n+1,nx[i])-bx;
ny[i]=lower_bound(by+1,by+n+1,ny[i])-by;
}
for (int i=1;i<=m;i++){
int t;
cin>>t;
tx[1]-=2;
tx[nx[t]]+=2;
tx[nx[t]+1]+=2;
tx[n+1]-=2;
ty[1]-=2;
ty[ny[t]]+=2;
ty[ny[t]+1]+=2;
ty[n+1]-=2;
}
for (int i=1;i<=n;i++) tx[i]+=tx[i-1],ty[i]+=ty[i-1];
for (int i=1;i<=n;i++){
int ax=bx[nx[i]]+tx[nx[i]];
int ay=by[ny[i]]+ty[ny[i]];
cout<<(ax+ay)/2<<" "<<(ax-ay)/2<<"\n";
}
return 0;
}
T4 激光【NOIP2025模拟赛T4】
题目难度:\(\color{#9D3DCF} 省选/NOI-\)
算法标签:动态规划,线段树优化dp