本题链接:Problem - C - Codeforces
题目:
样例:
|
2 3 5 0 2 2 |
思路:
数学+模拟。
根据题意,一前一后的攻击,攻击k次后,总共击落舰队多少个。
如果单纯模拟,肯定会TLE,所以要加上数学推导一下。
代码详解如下:
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
#include <unordered_map>
#define endl '\n'
#define int long long
#define YES puts("YES")
#define NO puts("NO")
#define umap unordered_map
#define All(x) x.begin(),x.end()
#pragma GCC optimize(3,"Ofast","inline")
#define IOS std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
using namespace std;
const int N = 2e6 + 10;
inline void solve();
signed main()
{
// freopen("a.txt", "r", stdin);
IOS;
int _t = 1;
cin >> _t;
while (_t--)
{
solve();
}
return 0;
}
int n,x,k;
inline void solve()
{
cin >> n >> k;
deque<int>q;
for(int i = 0;i < n;++i)
{
cin >> x;
q.emplace_back(x);
}
// 留最后一个判断是否能击落舰队
while(q.size() > 1 and k)
{
int mins = min(q.front(),q.back());
// 这里 mins << 1 是平衡的,前后攻击一次,总攻击两次
// 当 k 不符合前后攻击完一次,说明 k 会用完
if(k < (mins << 1))
{
// 这里平分前后攻击的 k 次, k % 2 是判断最后一次攻击是否会回到前面
q.front() -= (k >> 1) + (k % 2);
q.back() -= (k >> 1);
k = 0; // 用完 k
}else
{
// 前后攻击 mins 次
q.front() -= mins;
q.back() -= mins;
k -= (mins << 1); // 总攻击 mins * 2 次
}
// 扫尾,如果击落舰队后,去除该舰队
if(!q.front()) q.pop_front();
if(!q.back()) q.pop_back();
}
int ans = n - q.size(); // 计算最后击落的舰队数量
// 这里的 (q.size() and q.front() <= k) 是判断最后的一个舰队是否也可以击落
cout << ans + (q.size() and q.front() <= k) << endl;
}