2025.8.3.模拟赛题目及代码记录
题面原来是PDF,直接拿deepseek提取的,可能有的地方有语误,但整体还好(雾)
T1 游戏(game)
题目描述
- 有 \(n\) 位小朋友玩游戏,初始只有 1 号小朋友(计数器值为 \(x_1\)),之后 \(2 \sim n\) 号小朋友按顺序加入。
- 每个小朋友有一个计数器,初始值由输入给出。每按一次按钮,该小朋友的计数器值 \(+1\)。
- 当相邻两个小朋友的计数器值相同时,他们会“串手”,之后其中一人按按钮时另一人也会同步增加。
- 目标:通过按按钮使圈中任意相邻两个小朋友都串手。
- 加入规则:第 \(i\) 号小朋友(\(i \geq 2\))加入时,插入到当前圈中编号为 \(e_i\) 的小朋友的下一个位置。
- 任务:对每个 \(k\)(\(2 \leq k \leq n\)),输出加入第 \(k\) 个小朋友后,达成目标的最少按按钮次数。
输入格式
从文件 game.in 读取:
- 第一行:整数 \(n\)(小朋友总数)。
- 第二行:\(n\) 个整数 \(x_1, x_2, \dots, x_n\)(初始计数器值)。
- 第三行:\(n-1\) 个整数 \(e_1, e_2, \dots, e_{n-1}\)(\(e_i\) 表示第 \(i+1\) 号小朋友插入到编号 \(e_i\) 的后面)。
输出格式
输出到文件 game.out:
- \(n-1\) 行,每行一个整数,表示加入第 \(2,3,\dots,n\) 号小朋友后的最少按按钮次数。
样例输入 1
4
2 3 4 1
1 2 3
样例输出 1
1
2
3
样例解释
- 加入 2 号后:圈为 \([1,2]\),计数器 \([2,3]\)。让 1 号按 1 次,两人串手。
- 加入 3 号后:圈为 \([1,2,3]\),计数器 \([2,3,4]\)。先让 1 号按 1 次(\([3,4,4]\)),1 和 2 串手;再让 1 号按 1 次(\([4,4,4]\))。
- 加入 4 号后:圈为 \([1,2,3,4]\),计数器 \([2,3,4,1]\)。分三步操作:1 号按 1 次(\([3,4,4,1]\))→ 1 和 2 串手;1 号再按 1 次(\([4,4,4,1]\));2 号按 1 次(\([5,5,5,2]\))→ 全串手。
数据范围
- \(1 \leq n \leq 10^6\)
- \(1 \leq x_i \leq 10^9\)
T1 代码 —— AC
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=1000005;
ll a[MAXN];
int nxt[MAXN];
int main()
{
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
nxt[1]=1;
ll S=0;
for(int i=2;i<=n;i++)
{
int pos;
scanf("%d",&pos);
int y=pos;
int z=nxt[y];
S-=llabs(a[y]-a[z]);
S+=llabs(a[y]-a[i]);
S+=llabs(a[i]-a[z]);
nxt[y]=i;
nxt[i]=z;
printf("%lld\n",S/2);
}
fclose(stdin);
fclose(stdout);
return 0;
}
T2 买冰棍(ice)
题目描述
- 未来 \(n\) 天需发放冰棍,第 \(i\) 天需求 \(D_i\) 支。
- 每天可选择:
- 从厂商进货:单价 \(P_i\) 元/支。
- 使用库存冰棍:每支每天存储费 \(S\) 元。
- 冰棍容量上限 \(K\)(最多存 \(K\) 支)。
- 目标:满足每天需求的最小总花费。
输入格式
从文件 ice.in 读取:
- 第一行:三个整数 \(n, S, K\)(天数、单支存储费、容量)。
- 第二行:\(n\) 个整数 \(D_1, D_2, \dots, D_n\)(每天需求)。
- 第三行:\(n\) 个整数 \(P_1, P_2, \dots, P_n\)(每天进货单价)。
输出格式
输出到文件 ice.out:
- 一个整数,表示最小总花费。
样例输入 1
3 1 2
2 1 2
3 6 6
样例输出 1
21
样例解释
- 第 1 天:买 4 支(花费 \(4 \times 3 = 12\)),用 2 支满足需求,存 2 支(存储费 \(2 \times 1 = 2\))。
- 第 2 天:用库存 1 支(无进货费),剩余 1 支继续存储(存储费 \(1 \times 1 = 1\))。
- 第 3 天:买 1 支(花费 \(1 \times 6 = 6\)),加库存 1 支满足需求。
- 总花费:\(12 + 2 + 1 + 6 = 21\)。
数据规模分级
| 数据范围 | 满足条件 | 数据比例 |
|---|---|---|
| 测试点1~10% | $ n \leq 2 $ | 10% |
| 测试点11%~40% | $ n \leq 3000 $ | 30% |
| 测试点41%~60% | $ n \leq 10^5 $ | 20% |
| 测试点61%~80% | $ V \leq 10 $ | 20% |
| 测试点81%~100% | 无特殊限制 | 20% |
全局约束 (100% 数据)
- $ 1 \leq \mathbf{n} \leq 2 \times 10^6 $
- $ 0 \leq \mathbf{m, V, D_i, P_i} \leq 2 \times 10^6 $
注:
- 百分比为累加覆盖(如 40% 的数据包含 10% 的部分)
- ( D_i ) 和 ( P_i ) 表示第 ( i ) 项的属性值
- ( m ) 为附加变量,具体含义依题目而定
T2 代码 —— 10分 (骗来的)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,m,V,ans=LLONG_MAX;;
int main()
{
freopen("ice.in","r",stdin);
freopen("ice.out","w",stdout);
cin>>n>>m>>V;
vector<ll> D(n+1),P(n+1);
for(int i=1;i<=n;i++)
cin>>D[i];
for(int i=1;i<=n;i++)
cin>>P[i];
if(n==1)
{
cout<<D[1]*P[1];
return 0;
}
if(n==2)
{
for(ll x=D[1];x<=D[1]+V;x++)
{
ll s1=x-D[1];
if(s1>V)
break;
ll n2=max(0LL,D[2]-s1);
ll cost=x*P[1]+n2*P[2]+m*(2*s1+n2-D[2]);
ans=min(ans,cost);
}
cout<<ans;
return 0;
}
srand(static_cast<unsigned long long>(time(0)));//随机数发力了!......吗?当然没有,心理安慰罢了
ans=ll(rand()%100000001);
cout<<ans;
fclose(stdin);
fclose(stdout);
return 0;
}
T3 仓库位置(warehouse)
题目描述
- \(n\) 个仓库位于一条直线上,坐标 \(x_i\)。
- 仓库类型:
- 类型 1:新仓库,可直接开门。
- 类型 2:老仓库,需钥匙(钥匙存放在另一仓库 \(k_i\) 中)。
- 检查员从任意位置出发,求检查所有仓库的最小移动距离(移动距离为坐标差的绝对值)。
输入格式
从文件 warehouse.in 读取:
- 第一行:整数 \(n\)(仓库数)。
- 接下来 \(n\) 行:
- 若新仓库:
x_i 1 - 若老仓库:
x_i 2 k_i(\(k_i\) 是钥匙所在仓库编号)。
- 若新仓库:
输出格式
输出到文件 warehouse.out:
- 一个整数,表示最小移动距离。
样例输入 1
6
1 1
2 1
3 2 4
4 1
5 2 4
6 1
样例输出 1
7
样例解释
- 检查顺序:\(6 \to 4\)(取钥匙)$ \to 5 \to 4 \to 3 \to 2 \to 1$。
- 移动路径:\(|6-4| + |4-5| + |5-4| + |4-3| + |3-2| + |2-1| = 2+1+1+1+1+1=7\)。
数据范围与约定
| 数据比例 | 满足条件 |
|---|---|
| 20% | $ n \leq 20 $ |
| 10% | 所有 $ y[i] = 1 $(独立子集) |
| 20% | $ x[i] \leq 10 $(独立子集) |
全局约束(100% 数据)
- $ 1 \leq n \leq 10^6 $
- $ 0 \leq x_i \leq 10^{12} $
- $ y[i] \in {1, 2} $
- 特殊约束:当 $ y[i] = 2 $ 时,保证 $ y[x[i]] = 1 $
注:
- 分层数据中的"另外"表示独立测试点(不与其他条件重叠)
- $ x_i $ 取值范围极大($ 10^{12} $),但实际索引操作时需注意有效范围
- 当 $ y[i]=2 $ 时,$ x[i] $ 指向的位置 $ y $ 值必为 1
T3 代码 —— 10分 最好骗的一集()
#include<bits/stdc++.h>
using namespace std;
int n;
long long Max=LLONG_MIN,Min=LLONG_MAX;
bool spc=1;
int main()
{
freopen("warehouse.in","r",stdin);
freopen("warehouse.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)
{
long long a,b,c;
cin>>a>>b;
Max=max(Max,a);
Min=min(Min,a);
if(b==2)
{
spc=0;
cin>>c;
}
}
if(spc)
{
cout<<Max-Min;
return 0;
}
srand(static_cast<unsigned long long>(time(0)));//祖传随机数()
unsigned long long ans=rand()%100000001;
cout<<ans;
fclose(stdin);
fclose(stdout);
return 0;
}
T4 骑车(ride)
题目描述
- \(n\) 个景点构成树形结构,边权为 1。
- 骑行计划:长度为 \(m+1\) 的序列 \(p_0, p_1, \dots, p_m\)(从 \(p_0\) 出发,依次沿最短路径到 \(p_1, p_2, \dots, p_m\))。
- 景点 \(i\) 的饮料价格为 \(a_i\)。骑行中可在景点买/卖饮料(支架仅容 1 瓶),收益 = 卖出价 \(-\) 买入价。
- 目标:
- 最大化总收益。
- 求最大化收益的方案数(模 \(10^4+7\))。
- 动态事件:\(Q\) 次修改景点价格,每次修改后需回答上述两个值。
输入格式
从文件 ride.in 读取:
- 第一行:三个整数 \(n, m, Q\)(景点数、骑行段数、事件数)。
- 第二行:\(n\) 个整数 \(a_1, a_2, \dots, a_n\)(景点初始价格)。
- 接下来 \(n-1\) 行:每行两个整数 \(u, v\)(边)。
- 接下来一行:\(m+1\) 个整数 \(p_0, p_1, \dots, p_m\)(骑行计划)。
- 接下来 \(Q\) 行:每行两个整数 \(r, y\)(将景点 \(r\) 的价格改为 \(y\))。
输出格式
输出到文件 ride.out:
- \(Q+1\) 行:
- 第 1 行:初始价格下的答案。
- 第 \(i+1\) 行:第 \(i\) 次修改后的答案。
- 每行两个整数:最大收益、方案数(模 \(10^4+7\))。
样例输入 1
5 2 1
1 2 3 4 5
1 2
1 3
1 4
4 5
2 3 5
1 0
样例输出 1
6 1
4 2
样例解释
- 初始价格:
- 路径:\(2 \to 1 \to 3 \to 1 \to 4 \to 5\)。
- 最优:\(2\) 号买(\(2\) 元)→ \(3\) 号卖(\(3\) 元,赚 \(1\))→ \(1\) 号买(\(1\) 元)→ \(5\) 号卖(\(5\) 元,赚 \(4\))。总收益 \(5\),方案唯一。
- 修改后(景点 \(1\) 价格变 \(0\)):
- 最大收益 \(4\),方案有两种(详见题目)。
数据范围
- \(1 \leq n, m \leq 10^6\)
- \(0 \leq Q \leq 10^5\)
- \(1 \leq a_i, y \leq 10^9\)

浙公网安备 33010602011771号