题目背景
卷王来到了他的好朋友 bj12z_jiasiyuan 的农场,打算在那里过上一晚。但是在看新闻时,他们获得了一个不幸的消息,一场陨石雨就快要降临了……
## 题目描述
bj12z_jiasiyuan 的农场里有 n 间牛棚,编号为 1 到 n。第 i 间牛棚的防御值为 ai。
陨石雨将会在 t 秒后来临。在陨石雨来临的时候,会有 m 块陨石撞击牛棚,第 i 块陨石会撞击到第 xi 间牛棚。当一块陨石撞击一间牛棚时,牛棚的防御值会减去 2 点。而当一间牛棚的防御值 ≤0时,牛棚会被破坏。
bj12z_jiasiyuan 有很多补给,每个补给可以给一间牛棚增加1点防御值。幸运的是,卷王可以从一间牛棚瞬移到另一间牛棚(瞬移不需花费任何时间),用补给给牛棚增加防御值。每次补给需要 1 秒的时间。
卷王只有 t 秒种的时间可以出去补给,他希望让被破坏的牛棚越少越好。请你输出最优策略下被保护的牛棚的数量。
输入格式
本题单个测试点内包含多组测试数据。
第一行一个整数 T,代表测试数据组数。接下来 T 组数据,每组数据共三行。
第一行三个整数 n,t,m,分别表示牛棚的数量,卷王补给的时间和陨石的数量。
接下来一行 n 个整数a1,a2,⋯,an,表示第 i 间牛棚的防御值。
最后一行 m 个整数 x1,x2,⋯,xm,表示第 i 块陨石将会撞击第 i 间牛棚。
输出格式
输出 T 行,每行一个整数,分别表示每组测试数据中最优策略下被保护的牛棚的数量。
输入 #1
1
4 3 5
2 1 3 5
3 1 2 4 3
输出 #1
3
输入 #2
4
3 4 2
5 2 4
2 1
3 2 20
6 6 6
1 3 3 1 2 1 1 1 2 2 2 1 1 3 1 2 2 3 3 1
2 0 2
1 2
1 1
5 3 12
4 5797 2 1 1
5 4 3 2 4 4 5 5 5 5 1 1
输出 #2
3
0
1
3
说明/提示
样例 1 解释
一种最优的补给方法是补给 1 号牛棚 1 点防御值,补给 2 号牛棚 2 点防御值。
在这种情况下,各牛棚防御值变化如下,其中蓝色数字代表初始防御值,绿色数字代表补给,红色数字代表陨石撞击:
- 1 号:2+1−2=1;
- 2 号:1+2−2=1;
- 3 号:3−2−2=−1;
- 4 号:5−2=3。
有且仅有 3 号牛棚被破坏,可保护三个牛棚。
### 数据规模与约定
对于 100% 的数据,1≤xi≤n≤5×103,1≤m≤106,0≤t≤106,1≤ai≤106,1≤T≤5×103。保证单个测试点内所有测试数据 n 的总和不超过 5×104,所有测试数据 m 的总和不超过 3×106。
| 测试点编号 | 特殊限制 |
|---|---|
| 1,2 | T=1,n=1 |
| 3,4 | T=1,每间牛棚恰好被击中一次 |
| 5 | T=1,1≤xi≤n≤100 |
| 6 | T=1 |
| 7 | 1≤xi≤n≤100 |
| 8∼10 | 无特殊限制 |
#include<bits/stdc++.h> //万能头文件
using namespace std;
int T,n,t,m,a[5005],x[1000005],ans;
//总测试组数T,牛棚总数n,补给总时间t,陨石总数m,所有牛棚的防御值a数组,被陨石撞击的牛棚编号x数组,被保护的牛棚总数的最大值ans
int main(){
cin>>T; //输入总测试组数
for (int i=1;i<=T;i++) { //通过循环进行测试
cin>>n>>t>>m; //输入牛棚总数,补给总时间,陨石总数
for (int i=1;i<=n;i++) {
//先输入所有牛棚的防御值
cin>>a[i]; //将它们存进a数组
}
for (int i=1;i<=m;i++) {
//然后输入被陨石撞击的牛棚编号
cin>>x[i]; //将它们存进x数组
a[x[i]]-=2; //陨石砸一下掉两点防御值,所以把被陨石撞击的牛棚的牛棚的防御值都减二
}
sort(a+1,a+n+1); //将撞击后的所有牛棚的防御值从低到高排序
ans=0; //因为包含多组测试数据,所以把ans初始化一下
for (int i=n;i>=1;i--) {
//因为要保护尽可能多的牛棚,所以要倒着看
if (t>0&&a[i]<=0&&t>=1-a[i]) {
//首先要确保还有补给时间,其次是这个牛棚需要修补,最后是要确保修完之后不会超时
int b=1-a[i]; //定义b的值为修好编号为a[i]的牛棚的时间(不定义也可以)
t-=b; //将补给总时间减去修补时间
a[i]+=b; //这个牛棚修好了
}
if (a[i]>=1) { //如果牛棚的防御值大于等于一(没被破坏,成功被保护)
ans++; //增加被保护的牛棚总数
}
}
cout<<ans<<endl; //输出,别忘了换行
}
return 0;
}
PS:关于为什么要倒着看被砸后的牛棚防御值,是因为要修好更多的牛棚,不能死磕最小的那一个,这样会减少被保护的牛棚总数,这样的话有可能连最小的都补不好。比如说补给时间是50,防御值最小的是-100,但其他都是-1。
1058

被折叠的 条评论
为什么被折叠?



