本题链接: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;
}