A:Yet Another String Game
题目大意是Alice和Bob轮流对一个字符串进行操作,每轮他俩都必须选择一个字符并对其作出修改。Alice的目标是让这个字符串的字典序尽可能小,Bob的目标是让这个字符串的字典序尽可能大,问双方操作后的新字符串是什么。
按顺序模拟,注意考虑字符本身是’a’和’z’的情况即可。
#include<bits/stdc++.h>
#define close ios::sync_with_stdio(false)
using namespace std;
int main()
{
close;int T;cin>>T;
while(T--)
{
string s;cin>>s;
for(int i=0;i<s.length();++i)
{
if(i&1){if(s[i]=='z') s[i]='y';else s[i]='z';}
else{if(s[i]=='a') s[i]='b';else s[i]='a';}
}
cout<<s<<endl;
}
}
B:The Great Hero
题目大意是英雄和一群怪兽都有一个初始的攻击值和生命值,可以对同一个怪兽发动多次攻击,如果所有的怪兽死亡(哪怕英雄也在最后一轮战斗中死去)就输出“YES”,否则输出“NO”。
延续了B题不坑你几发罚时就誓不为人的风格 。首先要对怪兽按照攻击值从小到大排序,因为可能有b[i]%A!=0b[i]\%A!=0b[i]%A!=0,英雄就需要多打一次,也就给自身多造成了a[i]a[i]a[i]点的伤害。先处理小的目的是为了实现英雄血量不够的情况下还能发动最后一次攻击然后和最后一只怪兽一起死亡的现象。
#include<bits/stdc++.h>
#define close ios::sync_with_stdio(false)
using namespace std;
const int maxn=1e5+100;
typedef long long ll;
struct Monsters{
ll a,b,res;
bool operator < (const Monsters&mon) const{return a<mon.a;}
}m[maxn];
int main()
{
close;int T;cin>>T;
while(T--)
{
ll A,B,n;cin>>A>>B>>n;
for(int i=1;i<=n;++i) cin>>m[i].a;
for(int i=1;i<=n;++i) cin>>m[i].b;
int pos;sort(m+1,m+n+1);
for(int i=1;i<=n;++i)
{
pos=i;
ll h=(B/m[i].a)+(B%m[i].a!=0?1:0),l=(m[i].b/A)+(m[i].b%A!=0?1:0),r=min(h,l);
B-=m[i].a*r;m[i].b-=A*r;
if(B<=0) break;
}
if(pos<n) cout<<"NO\n";
else if(pos==n){
if(m[n].b<=0) cout<<"YES\n";
else cout<<"NO\n";
}
}
}
C:Searching Local Minimum
这是一道交互式问题,题目大意是只给定一个nnn(告诉你原序列是一个1~n的全排列中的一种),然后你的程序不断询问某个下标的值(最多不能超过100次询问),最后给出一个下标,满足ai<min(ai−1,ai+1)a_i<min(a_{i-1},a_{i+1})ai<min(ai−1,ai+1)。
二分三分都是可以的,我这里采用的是三分法,虽然整个图像并不是一个完全的单峰函数,但题目也没要求输出全局最小值,因此通过三分法一定能够找到一个局部的单峰性质,也就能输出最小值。使用三分法需要严格注意自己输出的下标的值是否合法,最后的值是否正确(可能会因为写法不同造成偏移)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+100;
int main()
{
int n;cin>>n;
int l=0,r=n+1,x1,x2;
while(l+1<r){
int mid=(l+r)/2;
cout<<"? "<<mid<<endl;fflush(stdout);
cin>>x1;
int midd=(mid+r)/2;
cout<<"? "<<midd<<endl;fflush(stdout);
cin>>x2;
if(x1<x2) r=midd;
else l=mid;
}
cout<<"! "<<l<<endl;fflush(stdout);
}
D1:Painting the Array I
题目大意是定义了一种运算segsegseg,代表将一个序列中连续相同的一段仅保留其中一个后,新序列的元素个数。然后给定你一个原序列A,你需要找到一个子序列a0a^0a0,a1=A−a0a^1=A-a^0a1=A−a0,问max{seg(a0)+(a1)}max\{seg(a^0)+(a^1)\}max{seg(a0)+(a1)}.
贪心了一个小时都没贪出来的菜狗,而且这种前面的选择会影响后续的我断然不敢往贪心上面猜,但这个世界就是这么的奇妙 。
使用贪心的策略,我们令last1,last2last1,last2last1,last2分别代表前两个序列的最后一个字符,现在来考虑第iii个字符:①last1==last2last1==last2last1==last2时,s[i]s[i]s[i]放在哪个序列后面都无所谓;②last1==s[i] && last2≠s[i]last1==s[i]\ \&\& \ last2\ne s[i]last1==s[i] && last2=s[i]时,直接放在序列2后就能得到最优解;③last2==s[i] && last1≠s[i]last2==s[i]\ \&\& \ last1\ne s[i]last2==s[i] && last1=s[i]时,直接放在序列1后就能得到最优解;④last1≠s[i] && last2≠s[i]last1\ne s[i]\ \&\& \ last2\ne s[i]last1=s[i] && last2=s[i]时,定义next[x]next[x]next[x]表示xxx在第iii个元素后的下一个出现位置,比较next[last1]next[last1]next[last1]和next[last2]next[last2]next[last2],谁小放在谁后。
#include<bits/stdc++.h>
#define close ios::sync_with_stdio(false)
using namespace std;
const int maxn=1e5+100;
int a[maxn],ind[maxn];
vector<int> v[maxn];
int main()
{
close;int n;cin>>n;
for(int i=1;i<=n;++i) cin>>a[i],v[a[i]].push_back(i);
int last1=0,last2=0,ans=0;
for(int i=1;i<=n;++i)
{
ind[a[i]]++;
if(last1==last2){
if(last1!=a[i]) last1=a[i],ans++;
}
else if(last1==a[i] && last2!=a[i]) last2=a[i],ans++;
else if(last2==a[i] && last1!=a[i]) last1=a[i],ans++;
else{
ans++;
int next1=n+1,next2=n+1;
if(ind[last1]<v[last1].size()) next1=v[last1][ind[last1]];
if(ind[last2]<v[last2].size()) next2=v[last2][ind[last2]];
if(next1<next2) last1=a[i];
else last2=a[i];
}
}
cout<<ans;
}
D2:Painting the Array II
题目大意和上述题目相同,仅仅是询问min{seg(a0)+(a1)}min\{seg(a^0)+(a^1)\}min{seg(a0)+(a1)}.
使用贪心的策略,我们令last1,last2last1,last2last1,last2分别代表前两个序列的最后一个字符,现在来考虑第iii个字符:①last1==last2last1==last2last1==last2时,s[i]s[i]s[i]放在哪个序列后面都无所谓;②last1==s[i] && last2≠s[i]last1==s[i]\ \&\& \ last2\ne s[i]last1==s[i] && last2=s[i]时,直接放在序列1后就能得到最优解;③last2==s[i] && last1≠s[i]last2==s[i]\ \&\& \ last1\ne s[i]last2==s[i] && last1=s[i]时,直接放在序列2后就能得到最优解;④last1≠s[i] && last2≠s[i]last1\ne s[i]\ \&\& \ last2\ne s[i]last1=s[i] && last2=s[i]时,定义next[x]next[x]next[x]表示xxx在第iii个元素后的下一个出现位置,比较next[last1]next[last1]next[last1]和next[last2]next[last2]next[last2],谁小放在另一个后。
#include<bits/stdc++.h>
#define close ios::sync_with_stdio(false)
using namespace std;
const int maxn=1e5+100;
int a[maxn],ind[maxn];
vector<int> v[maxn];
int main()
{
close;int n;cin>>n;
for(int i=1;i<=n;++i) cin>>a[i],v[a[i]].push_back(i);
int last1=0,last2=0,ans=0;
for(int i=1;i<=n;++i)
{
ind[a[i]]++;
if(last1==last2){
if(last1!=a[i]) last1=a[i],ans++;
}
else if(last1==a[i] && last2!=a[i]) continue;
else if(last2==a[i] && last1!=a[i]) continue;
else{
ans++;
int next1=n+1,next2=n+1;
if(ind[last1]<v[last1].size()) next1=v[last1][ind[last1]];
if(ind[last2]<v[last2].size()) next2=v[last2][ind[last2]];
if(next1<next2) last2=a[i];
else last1=a[i];
}
}
cout<<ans;
}