A - A
对于一个由非负整数构成的多重集合T,我们定义:
sum(T)表示T中所有元素的总和。例如,若T={0,1,1,3},则sum(T)=0+1+1+3=5。
mex(T)指不在T中的最小非负整数。比如T={0,1,1,3}时,mex(T)=2,因为2是最小的缺失非负整数。
现给定一个大小为n的非负整数多重集合S。初始分数为0,你可以不限次数和顺序(也可不操作)执行以下两种操作:
- 选择子集S’⊆S,将sum(S’)加入分数,并从S中移除S’;
- 选择子集S’⊆S,将mex(S’)加入分数,并从S中移除S’。
求你能获得的最大分数。
找规律,因为我们可以发现,只要每次挑出一个0出来,可以比原来直接加上去多1,所以我们先对每一个0进行一次mex操作,其余的数直接sum起来就行了。
#include <bits/stdc++.h>
using namespace std;
int s[55],t[55];
int main(){
int q;
cin>>q;
while(q--){
memset(t,0,sizeof t);
int n,sum=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i];
t[s[i]]++;
sum+=s[i];
}
cout<<sum+t[0]<<endl;
}
return 0;
}
B - B
一家公司有 n 名员工,编号为 1 到 n。每位员工要么没有直属上级,要么只有一个直属上级(其上级必须是其他编号的员工)。员工 A 是员工 B 的上级需满足以下条件之一:
- A 是 B 的直属上级;
- B 有直属上级 C,而 A 是 C 的上级。
公司不存在管理循环,即没有员工是自己的上级。
现在公司要举办派对,需要将员工分组,要求:
- 每位员工必须且只能属于一个小组;
- 同一小组内不能存在上级关系(即不能有员工 A 和 B 满足 A 是 B 的上级)。
求最少需要分成多少个小组。
因为同一组不能有祖孙关系,也就是说每一组一定在同一层,哪怕不在同一颗树内,所以我们只要找到深度最深的那颗树的深度就是我们的答案。
参考:
该组数据答案为3。
#include <bits/stdc++.h>
using namespace std;
int zz[2005];//每棵树的根节点
vector<int> E[2005];
int yy[2005];//用来存储每棵树的深度
bool f[2005];
void dfs(int x,int fa,int cc,int sd){
if(!f[sd])yy[cc]++;
f[sd]=1;
for(int i=0;i<E[x].size();i++){
int v=E[x][i];
if(v==fa)continue;
dfs(v,x,cc,sd+1);
}
}
int main(){
int n,cs=0;//多少个点,多少个祖宗
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
if(x!=-1){
E[i].push_back(x);
E[x].push_back(i);
}else{
zz[++cs]=i;
}
}
for(int i=1;i<=cs;i++){
memset(f,0,sizeof f);
dfs(zz[i],0,i,1);
}
int mx=0;
for(int i=1;i<=cs;i++){
mx=max(mx,yy[i]);
}
cout<<mx;
return 0;
}
C - C
课间休息时,食堂里排着一条由n名男生女生组成的队伍。最初,孩子们按照进入食堂的顺序站好。但不久后,男生们开始因站在女生前面而感到不自在,于是每秒都会让前方的女生向前移动。
具体来说,队伍的位置编号为1到n,其中1号位置的人最先接受服务。若在x时刻,第i个位置是男生而第(i+1)个位置是女生,那么在x+1时刻,这两个位置会互换:第i个位置变为女生,第(i+1)个位置变为男生。时间以秒为单位计算。
已知初始时刻队伍的排列情况,请计算出t秒后队伍的最后状态。
模拟大水题,由于n<=50,所以我们丝毫不慌。我们用bool数组模拟男女生,经过t次更新,最终直接输出目前bool数组的状态。
#include <bits/stdc++.h>
using namespace std;
bool f[55],ff[55];//使用bool更加方便,记得输出要变成字符
int main(){
int n,t;
cin>>n>>t;
for(int i=1;i<=n;i++){
char x;
cin>>x;
if(x=='B'){
f[i]=1;
}
}
for(int i=1;i<=t;i++){
ff[1]=f[1];
for(int k=1;k<n;k++){
ff[k+1]=f[k+1];//这么写纯属偷懒
if(f[k]&&!f[k+1]){//看男生后面是不是女生
swap(ff[k],ff[k+1]);
}
}
for(int k=1;k<=n;k++){
f[k]=ff[k];
}
}
for(int i=1;i<=n;i++){
if(f[i]){
cout<<'B';
}else{
cout<<'G';
}
}
return 0;
}
D - D
国王独自镇守棋盘。虽孤军奋战,却毫不气馁,因为他肩负着守卫王国的重任。此刻,他需要尽快从当前位置s前往t方格进行正式访问。向来注重效率的国王,希望以最少的步数完成这次移动。

国王的移动规则如下:每次可向任意相邻方格移动,包括横向、纵向及斜向共8个方向。具体移动指令对应为:
- 基本方向:L(左)、R(右)、U(上)、D(下)
- 斜向组合:LU(左上)、LD(左下)、RU(右上)、RD(右下)
也是模拟水题,直接dfs爆搜就行了,每次看走那边更近,直接走向那一边。应该不会有人打表吧……有4096种情况
#include <bits/stdc++.h>
using namespace std;
int xs,xe,ys,ye,b[30];
string fx[10]={"","U","D","L","R","LU","RU","LD","RD"};//八个方向,注意顺序
//网上,网下,王座,网友,坐上,忧伤,坐下,游侠,@一下你打出来的是啥吧!
void dfs(int x,int y){
if(xe==x&&ye==y){//走完了
return;
}
if(xe<x&&ye==y){//往上
b[++b[0]]=1;
dfs(x-1,y);
}
if(xe>x&&ye==y){//往下
b[++b[0]]=2;
dfs(x+1,y);
}
if(xe==x&&ye<y){//往左
b[++b[0]]=3;
dfs(x,y-1);
}
if(xe==x&&ye>y){//往右
b[++b[0]]=4;
dfs(x,y+1);
}
if(xe<x&&ye<y){//左上
b[++b[0]]=5;
dfs(x-1,y-1);
}
if(xe<x&&ye>y){//右上
b[++b[0]]=6;
dfs(x-1,y+1);
}
if(xe>x&&ye<y){//左下
b[++b[0]]=7;
dfs(x+1,y-1);
}
if(xe>x&&ye>y){//右下
b[++b[0]]=8;
dfs(x+1,y+1);
}
}
int main(){
char x,y;
cin>>x>>xs>>y>>xe;
xs=8-xs+1;
xe=8-xe+1;
ys=int(x)-'a'+1;
ye=int(y)-'a'+1;//一系列处理
dfs(xs,ys);//出发喽
cout<<b[0];//输出总共走了几步
for(int i=1;i<=b[0];i++){
cout<<endl<<fx[b[i]];
}
return 0;
}
E - E
你有一副包含 n 张卡牌的牌堆,从上到下依次编号为 1 到 n(顶部牌为 1,底部牌为 n)。每张牌都有一个颜色属性:第 i 张牌的颜色为 a i a_i ai。
现在需要处理 q 个查询。对于第 j 个查询:
- 在牌堆中找出颜色为 t j t_j tj 且位置最高的牌(即索引最小的牌)
- 输出该牌的位置
- 将该牌从当前位置取出,并放置到牌堆顶部你有一副包含 n 张卡牌的牌堆,从上到下依次编号为 1 到 n(顶部牌为 1,底部牌为 n)。每张牌都有一个颜色属性:第 i 张牌的颜色为 a i a_i ai。
第一行包含两个整数n和q ( 2 ≤ n ≤ 3 × 10 5 , 1 ≤ q ≤ 3 × 10 5 ) (2 ≤ n ≤ 3×10⁵,1 ≤ q ≤ 3×10⁵) (2≤n≤3×105,1≤q≤3×105),分别表示牌堆中的卡牌数量和查询数量。
第二行包含n个整数 a 1 , a 2 , . . . , a n ( 1 ≤ a i ≤ 50 ) a₁, a₂, ..., a_n(1 ≤ aᵢ ≤ 50) a1,a2,...,an(1≤ai≤50),表示每张卡牌的颜色。
第三行包含q 个整数 t 1 , t 2 , . . . , t q ( 1 ≤ t j ≤ 50 ) t₁, t₂ , ..., t_q(1 ≤ tⱼ ≤ 50) t1,t2,...,tq(1≤tj≤50),表示查询的颜色。题目保证所有查询的颜色都存在于牌堆中。
这题有点意思,因为n和q有3e5,所以就不能暴力,而且每次还要进行修改。
但我们看到了一个东西,1 ≤ aⱼ ≤ 50,题目故意设这么小干什么呢?当然是让我们水题做题的呀!
于是,我们可以使用一个数组来统计每个数最早出现在哪个位置,每次询问直接输出。
然后我们就要对这个数组进行更新,循环找出位于这个数之前的数,让他们的最早出现的位置++,最后再让这个数最早出现的位置变成1。
#include <bits/stdc++.h>
using namespace std;
int a[300005],b[55];
int main(){
int n,q,mx=0;
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
if(!b[a[i]]){
b[a[i]]=i;
}
mx=max(mx,a[i]);
}
while(q--){
int x;
cin>>x;
cout<<b[x]<<" ";
for(int i=1;i<=mx;i++){//i循环到50也行
if(b[i]<b[x]){
b[i]++;
}
}
b[x]=1;
}
return 0;
}
F - F
弗拉德回家时,发现有人将旧恒温器的温度重新设置成了a。
该恒温器的温度只能在[l,r]范围内调节(包括端点值),且每次温度变化的绝对值必须不小于x。具体来说,当满足|a-b|≥x且l≤b≤r时,可以通过单次操作将温度从a调整到b。
给定参数l、r、x、a和b,要求计算从温度a调整到b所需的最少操作次数。若无法实现温度调整,则需要给出相应说明。
这题,嗯,额,嘶,说白了就是分支结构,详细直接看以下代码。
#include <bits/stdc++.h>
using namespace std;
int main(){
int t;
cin>>t;
while(t--){
long long l,r,x,a,b;//温度范围及最小温度变化值及初始温度和最终温度
cin>>l>>r>>x>>a>>b;
if(a>b){
swap(a,b);
}
if(a<l||b>r){
//预期的温度超过了温度范围
cout<<-1<<endl;
continue;
}
if(a==b){
//初始温度和最终温度相同
cout<<0<<endl;
continue;
}
if(b-a>=x){
//如果他们之间的距离大于等于最小温度变化值
cout<<1<<endl;
continue;
}
if(b+x<=r||a-x>=l){
//如果可以通过 先增加若干温度再减到最终温度 或 先减少若干温度再增加到最终温度
cout<<2<<endl;
continue;
}
if(a+x<=r&&b-x>=l){
//如果可以先增加若干温度再减少若干温度再增加到最终温度 或 反之
cout<<3<<endl;
continue;
}
cout<<-1<<endl;//否则还是不行
}
return 0;
}
发一条友善的评论吧!

被折叠的 条评论
为什么被折叠?



