A. Short Sort
题意
有三张带有字母 a 、 b 、 c 的卡片按某种顺序排成一行。您可以执行以下操作最多一次:
-选两张牌,然后交换
操作后行是否可能变为 abc ?如果可能,则输出“Yes”,否则输出“No”。
分析
只要有一个字母的位置是正确的就可以变成abc
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
int main()
{
int t;cin>>t;
while(t--)
{
string s;
cin>>s;
if(s[0]=='a' || s[1]=='b' || s[2]=='c') puts("Yes");
else puts("No");
}
return 0;
}
B. Good Kid
题意
给定n个元素的数组a,现在可以将其中一个元素值加1,求操作完之后最大的元素之积
分析
给最小的元素加1即可
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
const int N=15;
int main()
{
int t;cin>>t;
while(t--)
{
int n;cin>>n;
int f[N];
ll ans=1;
for(int i=1;i<=n;i++) cin>>f[i];
sort(f+1,f+n+1);
f[1]++;
for(int i=1;i<=n;i++) ans*=f[i];
cout<<ans<<endl;
}
return 0;
}
C. Target Practice
题意
给定一个10 x 10的靶子,如图最外圈得1分,最内圈得5分,击中用"x"表示,计算最终得分
分析
第一种方法直接打出得分表
第二种方法对于出现x的单元格,其分数值一定是行号,列号,11-行号,11-列号的最小值
代码
1.丑陋的打表
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
int score[10][10]=
{1,1,1,1,1,1,1,1,1,1,
1,2,2,2,2,2,2,2,2,1,
1,2,3,3,3,3,3,3,2,1,
1,2,3,4,4,4,4,3,2,1,
1,2,3,4,5,5,4,3,2,1,
1,2,3,4,5,5,4,3,2,1,
1,2,3,4,4,4,4,3,2,1,
1,2,3,3,3,3,3,3,2,1,
1,2,2,2,2,2,2,2,2,1,
1,1,1,1,1,1,1,1,1,1};
char map[11][11];
int main()
{
int t;cin>>t;
while(t--)
{
for(int i=1;i<=10;i++) scanf("%s",map[i]+1);
ll ans=0;
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
{
if(map[i][j]=='X') ans+=score[i-1][j-1];
}
}
cout<<ans<<endl;
}
return 0;
}
2.找规律
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
const int N=15;
char map[N][N];
int main()
{
int t;cin>>t;
while(t--)
{
for(int i=1;i<=10;i++) scanf("%s",map[i]+1);
ll ans=0;
for(int i=1;i<=10;i++)
{
for(int j=1;j<=10;j++)
{
if(map[i][j]=='X')
{
ans+=min({i,j,11-i,11-j});
}
}
}
cout<<ans<<endl;
}
return 0;
}
D. 1D Eraser
题意
您将得到一张长为 n个单元格的纸条 s。每个单元格不是黑色就是白色。在操作中,您可以取任意 k个连续的单元格,并将它们全部变成白色。B表示黑色,W表示白色
找出移除所有黑色单元所需的最小操作次数。
分析
只要在长度为k的区间内都可以一次染成白色,那么计算出有几个这样长度为k且包含黑色的区间即可
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
int main()
{
int t;cin>>t;
while(t--)
{
string s;
int n,k;
cin>>n>>k>>s;
ll ans=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='B')
{
ans++;
i+=k-1;
}
}
cout<<ans<<endl;
}
return 0;
}
E. Building an Aquarium
题意
你喜欢鱼,这就是你决定建一个水族馆的原因。你有一块由 n 根柱子组成的珊瑚,其中第 i 根柱子有 ai个单位高。之后,您将在珊瑚周围建造一个水箱,如下所示:
-选择一个整数 ℎ≥1 -水箱的高度。
在水箱的两侧建造高度为 ℎ 的墙。-然后,将水箱注满水,使每列的高度为 ℎ ,
除非珊瑚高于 ℎ ,否则不应向此列添加水。例如,对于 a=[3,1,2,4,6,2,5] 和高度ℎ=4 ,您最终将使用总共 w=8单位的水。
您最多可以使用 x 个单位的水来装满水箱,但您希望尽可能建造最大的水箱。
您可以选择的 h 的最大值是多少?
分析
求最大值,且答案具有单调性,二分答案即可
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
const int N=2e5+10;
ll f[N];
int n,m;
bool check(ll x)
{
ll ans=0;
for(ll i=1;i<=n;i++)
{
ans+=max(0ll,x-f[i]);
if(ans>m) return false;
}
return true;
}
int main()
{
int t;cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>f[i];
ll l=0,r=1e18;
while(l+1<r)
{
ll mid=(l+r)>>1;
if(check(mid)) l=mid;
else r=mid;
}
if(check(l)) cout<<l<<endl;
else cout<<r<<endl;
}
return 0;
}
F. Money Trees
题意
现有n棵树,a数组为每棵树包含的果实数组,b数组为每棵树的高度数组,现给定一个数k,
现求一个区间,保证区间内的每个i都符合b[i]%b[i+1]==0并且该区间内的果实之和不大于k,输出该区间的最大长度
分析
用双指针维护区间记录最大值即可,其中果实之和可以用前缀和记录
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
const int N=2e5+10;
int a[N],b[N];
ll s[N];
int main()
{
int t;cin>>t;
while(t--)
{
int n,k;cin>>n>>k;
for(int i=1;i<=n;i++)
{
cin>>a[i];
s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++) cin>>b[i];
ll ans=0;
ll l=1,r=1;
while(r<=n)
{
if(b[r-1]%b[r]) l=r;
while(s[r]-s[l-1]>k) l++;
ans=max(ans,r-l+1);
r++;
}
cout<<ans<<endl;
}
return 0;
}
G. ABBC or BACB
题意
给定一个只包含A,B的字符串s,每次可以执行下列操作的任意一种
1.将AB变为BC,获得一枚银币
2.将BA变为CB,获得一枚银币
求可能获得的最大银币
分析
对于字符串BAAAA,我们可以将BA变为CB,那么新串为CBAAA,直至变为CCCCB,那么获得的银币数恰好为4枚
对于字符串AAAAB,我们将AB变为BC,新串为AAABC,直至变为BCCCC,获得4枚银币
可以发现,每个B一定可以将一串连续的A全部变为银币,那么我们只需要计算出B的个数和连续的A的个数,选择将B个最长的连续A变为银币,此时银币数最多
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
//#include<queue>
//#include<map>
//#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
int main()
{
int t;cin>>t;
while(t--)
{
string s;
cin>>s;
ll nb=0;
for(int i=0;i<s.size();i++)
{
if(s[i]=='B') nb++;
}
vector<int>f;//每段连续a的个数
for(int i=0;i<s.size();i++)
{
if(s[i]=='A')
{
int j=i;
while(j<s.size() && s[j]=='A') j++;
f.emplace_back(j-i);
i=j-1;
}
}
sort(f.begin(),f.end(),greater<>());
ll ans=0;
for(int i=0;i<f.size() && i<nb;i++) ans+=f[i];
cout<<ans<<endl;
}
return 0;
}
H. Mad City
题意
给定一张n个点n条边的无向图,以及a和b的初始坐标,现在a想要抓到b,b非常聪明,可以预测到a的行动,两人同时开始行动,问a是否可以抓到b,如果抓不到,输出Yes,否则输出No
分析
首先n个点n条边的无向图,说明该图是一颗基环树。我们都知道树是n个点,n-1条边,基环树则在树的基础上多连接了一条边,这就导致它一定包含一个环。
引入了基环树之后,我们再来看,如果b想逃脱,那么他只能跑到环上和a不断地兜圈子,那么我们先找到环上的点是那些点,然后计算出a和b到这些点的最短距离,如果对于任意一个环上的点,a都能先一步比b到达,那么a一定能抓到b,反之只要有一个在环上点,b到这个点的距离比a小,那么b一定能逃脱
基环树:n个点n条边的连通图,一定包含一个环
找环:拓扑排序法,拓扑排序之后入度大于等于2的点即为环上的点
代码
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
//#include<map>
#include<vector>
//#include<set>
//#include<deque>
//#include<bitset>
//#include<functional>
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
typedef pair<int,int>PII;
const int N=2e5+10;
int de[N];//入度数组
vector<int>e[N];
int n,a,b;
void bfs(vector<int>&d,int x)//bfs求最短路
{
fill(d.begin(),d.end(),-1);
d[x]=0;
queue<int>q;
q.push(x);
while(!q.empty())
{
auto t=q.front();
q.pop();
for(auto ed:e[t])
{
if(d[ed]==-1)
{
d[ed]=d[t]+1;
q.push(ed);
}
}
}
}
void top_sort()//拓扑排序
{
queue<int>q;
for(int i=1;i<=n;i++)
{
if(de[i]==1) q.push(i);
}
while(!q.empty())
{
auto t=q.front();
q.pop();
for(auto ed:e[t])
{
if(de[ed]>1)
{
de[ed]--;
if(de[ed]==1) q.push(ed);
}
}
}
}
int main()
{
int t;cin>>t;
while(t--)
{
memset(de,0,sizeof de);
cin>>n>>a>>b;
for(int i=1;i<=n;i++)
{
int x,y;
cin>>x>>y;
e[x].emplace_back(y);
e[y].emplace_back(x);
de[x]++;
de[y]++;
}
vector<int>da(n+1),db(n+1);//ab点到其他点的最短距离
bfs(da,a);
bfs(db,b);
vector<int>circle;//环上点的集合
top_sort();
for(int i=1;i<=n;i++)
{
if(de[i]>=2) circle.emplace_back(i);
}
//for(int i=0;i<circle.size();i++) cout<<circle[i]<<endl;
int flag=0;
for(int i=0;i<circle.size();i++)
{
if(da[circle[i]]>db[circle[i]])
{
flag=1;
break;
}
}
if(flag) puts("YES");
else puts("NO");
for(int i=1;i<=n;i++) e[i].clear();
}
return 0;
}