C. Inhabitant of the Deep Sea
算法:模拟 贪心
题意:1~n个飞船在被撞击ai次后损坏 每次攻击飞船第一个和最后一个 直至飞船损坏 攻击k次
思路:因为是来回攻击 所以对前面攻击k/2+k%2次对后面攻击k/2次 前后进行遍历 减少前面飞船k/2的血量直至0 减少后面飞船k/2的血量直至0 然后遍历一遍求0的个数 (因为会有飞船会同时被前面和后面攻击到)
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;using ll = long long;using PLL = pair<ll,ll>;
const ll MAX = 1e18;const ll MIN = -1e18;const ll INF=0x3f3f3f3f;
const ll Q = 2e5+9;const ll MOD = 1e9 + 7;
ll a[Q];
void solve(){
ll n,m;cin>>n>>m;
for (ll i = 1; i <= n; i++)
{
cin>>a[i];
}
ll l=m/2+m%2,r=m/2;
for (ll i = 1; i <= n; i++)
{
if(a[i]<=l) l-=a[i],a[i]=0;
else {
a[i]-=l;break;
}
}
for (ll i = n; i >= 1; i--)
{
if(a[i]<=r) r-=a[i],a[i]=0;
else {
a[i]-=r;break;
}
}
ll num=0;
for (ll i = 1; i <= n; i++)
{
if(a[i]<=0) num++;
}
cout<<num<<"\n";
}
int main(){
ios;ll _=1;cin>>_;
while (_--)solve();
return 0;
}
D. Inaccurate Subsequence Search
算法:双指针 map
题意:给定一个a数组和b数组 选出b数组位数个a数组的连续数组组成一个新数组 然后重新排序后对b进行匹配 要使相同的个数尽可能的多 至少为k个的 连续子段的数量
思路:先开一个map记录一下b数组的数 假设b的数组位数为 m 使用双指针先指向 1 和 m 将 1 到 m 之间的数加入map2判断一下map里是否存在该数 若存在 则cnt++ 每次移动右指针 将新的数加入mp2 判断新数是否存在 判断左指针的数是否存在mp 若存在则 cnt-- 每次记录一下cnt是否>=k ans++
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;using ll = long long;using PLL = pair<ll,ll>;
const ll MAX = 1e18;const ll MIN = -1e18;const ll INF=0x3f3f3f3f;
const ll Q = 2e5+9;const ll MOD = 1e9 + 7;
ll a[Q],b[Q];
void solve(){
ll n,m,k;cin>>n>>m>>k;
for (ll i = 1; i <= n; i++)
{
cin>>a[i];
}
map<ll,ll>mp;
for (ll i = 1; i <= m; i++)
{
cin>>b[i];mp[b[i]]++;
}
ll ans=0;
map<ll,ll>cnt;ll now=0;
for (ll i = 1; i <= m; i++)
{
cnt[a[i]]++;
if(cnt[a[i]]<=mp[a[i]]) now++;
}
ll l=1,r=m;
if(now>=k) ans++;
while(r<n){
r++;
cnt[a[r]]++;
if(cnt[a[r]]<=mp[a[r]]) now++;
if(mp[a[l]]>=cnt[a[l]]) now--;
cnt[a[l]]--;
l++;
if(now>=k){
ans++;
}
}
cout<<ans<<"\n";
}
int main(){
ios;ll _=1;cin>>_;
while (_--)solve();
return 0;
}
E. Long Inversions
算法:贪心 模拟 排序
题意:给出一个长度为 n 的二进制字符串 s 。二进制字符串是仅由字符'1'和'0'组成的字符串。选择一个整数 k 选择字符串的 k 个连续字符并将其反转,即将所有'0'替换为'1',反之亦然。您需要使字符串中的所有字符都等于'1'。求最大的k。
思路:最值问题很容易想到二分 但这个题二分不适用,数据范围可以在O(n2)级别的 所以直接暴力 枚举k的个数 从n到1 验证可行性 每次从头开始遍历遇到0就将当前和当前位+k的数进行取反 遇到第一个可行的k 输出 return
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;using ll = long long;using PLL = pair<ll,ll>;
const ll MAX = 1e18;const ll MIN = -1e18;const ll INF=0x3f3f3f3f;
const ll Q = 2e5+9;const ll MOD = 1e9 + 7;string s;ll n;
ll a[5005];
bool check(ll x){
string t=s;
for (ll i = 0; i < n+n; i++)
{
a[i]=0;
}
ll now=0;
for (ll i = 0; i < n; i++)
{
now-=a[i];
if(now%2==1){
if(t[i]=='1') t[i]='0';
else t[i]='1';
}
if(t[i]=='0' and i <= n-x){
now++;a[i+x]++;
if(t[i]=='1') t[i]='0';
else t[i]='1';
}
}
for (ll i = 0; i < n; i++)
{
if(t[i]=='0') {
return false;
}
}
return true;
}
void solve(){
cin>>n;
cin>>s;
for (ll i = n; i >= 1; i--)
{
if(check(i)){
cout<<i<<"\n";
return;
}
}
}
int main(){
ios;ll _=1;cin>>_;
while (_--)solve();
return 0;
}
F. Unfair Game
算法:数学
题意:自己去读
思路:因为只有 1 2 3 4 四个数 且只有1+2 和 3能进行匹配 除此之外其他每个数都必须得是偶数个数 先判断当前符不符合1 和 2 和 3都是奇数个 若是 则ans+1 然后每个数每次进行自减两次 为一个胜利条件 算出所有的1 2 3 4能自减2的个数相加即可
#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
using namespace std;using ll = long long;using PLL = pair<ll,ll>;
const ll MAX = 1e18;const ll MIN = -1e18;const ll INF=0x3f3f3f3f;
const ll Q = 2e5+9;const ll MOD = 1e9 + 7;
void solve(){
ll a,b,c,d;cin>>a>>b>>c>>d;
ll ans=0;
if(c%2==1 and a%2==1 and b%2==1) ans++;
ans+=a/2+b/2+c/2+d/2;
cout<<ans<<"\n";
}
int main(){
ios;ll _=1;cin>>_;
while (_--)solve();
return 0;
}