189 8069 5689

寒假第一、二场合集-创新互联

寒假第一、二场合集
  • 写在前面
  • 第一场
    • 7-2 签到题
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • 我的代码
      • 总结
        • 问题分析
        • lowbit函数
    • 7-6 dh与学妹过桥
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • AC代码
      • 总结
        • 解题思路
    • 7-7 有多少个质数
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • 我的代码
      • AC代码
      • 总结:
        • 问题分析:
        • 埃氏筛
    • 7-8 天上也会掉馅饼
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • AC代码
      • 总结
        • 解题思路
    • 7-9 遍遍遍历
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • AC代码1
      • AC代码2
      • 总结
        • 解题思路
    • 7-10 无间道
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • 我的代码(不是正确的代码)
      • AC代码
      • 总结
        • 问题分析
        • 解题思路
    • 7-11 简单的图
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • AC代码
      • 总结
        • 解题思路
  • 第二场
    • 7-6 YooQ和olderciyuan玩石子
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • AC代码
      • 总结
        • 问题分析
        • 解题思路
        • 注意
    • 7-7 霸道
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • AC代码
      • 总结
        • 问题分析
        • 解题思路
        • 注意
    • 7-9 WaWa机
      • 题目内容
      • 输入格式
      • 输出格式:
      • 输入样例:
      • 输出样例
      • AC代码
      • 总结
        • 问题分析
        • 解题思路
  • 写在后面

10年积累的做网站、成都网站建设经验,可以快速应对客户对网站的新想法和需求。提供各种问题对应的解决方案。让选择我们的客户得到更好、更有力的网络服务。我虽然不认识你,你也不认识我。但先网站制作后付款的网站建设流程,更有罗定免费网站建设让你可以放心的选择与我们合作。写在前面

如果有佬发现文章中有任何问题(包括但不限于引用题目以及码的佬的文章的版权问题),欢迎随时踢我。

第一场

第一场共11题,AC6题,其中有一题数据不是特别完善,被我钻了空子。涉及知识点:位运算、 dp、 数论、 模拟、 二叉树、 图的构建

7-2 签到题 题目内容

小明和小东是生活在二进制世界的人,一天他们分别获得了一个十进制数,他们想通过将该十进制数分解成二进制数,然后取出其二进制下最小非零数值的部分进行比较,如果小明的更小那么输出"xiaoming",如果小东的更小输入“xiaodong”,如果一样小输出“same”。

输入格式

第一行输入一个整数 1≤t≤1000 , 代表测试数据的组数。

每组数据输入一行,每行两个正整数 x,y ,x是小明获得的数 , y是小东获得的数 .

保证所有输入数据 1≤x,y≤1e18.

输出格式:

参考题意输出格式即可。

输入样例:

2
1 1
2 1

输出样例

same
xiaodong

我的代码
#includeusing namespace std;
#define int long long
signed main()
{int t;
    cin>>t;
    while(t--)
    {long long a,b;
        long long ma=0,mb=0,x=0,y=0;
        cin>>a>>b;
        while(a)//计算数字a中出现第一个1前有多少个0
        {ma=a%2;//用十进制转二进制的方法取末位
            a/=2;
            if(ma==0)
                x++;
            else
                break;
        }
        while(b)//计算数字b中出现第一个1前有多少个0
        {mb=b%2;
            b/=2;
            if(mb==0)
                y++;
            else
                break;
        }
        if(x==y)
            cout<<"same"<<'\n';
        else if(x>y)
        {cout<<"xiaodong"<<'\n';
        }
        else
            cout<<"xiaoming"<<'\n';
    }
    return 0;
}
总结 问题分析

这题我练习的时候花了很多时间,主要是对“其二进制下最小非零数值的部分”的理解花了很长时间。在网上冲浪的时候,发现有一个叫lowbit()的函数能处理这个题目。

lowbit函数

lowbit(x)的值是x的二进制表达式中最低位的1所对应的十进制值,简单来说,lowbit(x)是将 x 转化成二进制数之后,只保留最低位(从右往左数,第一位)的1及其后面的0,截断前面的内容,然后再转成10进制数。

举个栗子🌰,lowbit(6)=2

代码码在这

int lowbit(int x)
{return x&(-x);
}

有个佬的总结挺好的,我就不赘述了,链接码在这
https://blog.csdn.net/weixin_44694201/article/details/118034246

注:
1:lowbit(x)不是一个封装好的函数,要自己手搓
2:lowbit(x)有几种不同的写法,比较推荐上面这种,容易理解

7-6 dh与学妹过桥 题目内容

吃完饭后dh和学妹一起走到了一条江边,有两列平行的石墩桥,每个石墩上都有一个小写字母,dh对学妹说:我走上面这列石墩,你走下面的石墩,我先走一个石墩然后你在你那列石墩跟着我走一个同样字母的石墩,一直向前走,直到过了这条河,你知道你最多能踩多少个石墩吗?你答的出来吗?

输入格式

输出两行字符串,表示两列石墩桥(字符串长度大不超过1000)

输出格式:

输出一个整数,表示最多走多少个石墩

输入样例:

abcdef
acebeee

输出样例

3

AC代码
#includeusing namespace std;
const int N =1e3+5;
#define int long long
char a[N],b[N];
int f[N][N];
signed main()
{scanf("%s%s",a,b);
    for (int i = 0;i< strlen(a); i ++)
        for (int j = 0; j< strlen(b); j ++)
        {if (a[i] == b[j])  f[i + 1][j + 1] = f[i][j] + 1;
            else f[i + 1][j + 1] = max(f[i][j + 1], f[i + 1][j]);
        }
    cout<< f[strlen(a)][strlen(b)]<< endl;
    return 0; 
}
总结

这题我写错了,后面借助网络的力量,发现理解错题目了。dh走一步,学妹不一定要走到dh站的石墩上的字母上,抽象一下就是典型的dp最长公共子序列(LCS)。

这里也把佬的总结码在这
https://blog.csdn.net/qq_62362934/article/details/125919681

注:佬的总结跟我的有点不一样

解题思路

1.设计状态(定义一个数组,确定其各维含义)

i表示当dh走到a的i位置,j表示学妹走到b的j位置,f[i][j]表示dh走到a的i位置,学妹走到b的j位置时,学妹走的石墩数。其中学妹走过的石墩上的字母,即为a的最长公共子序列,f[i][j]表示最长公共子序列的长度。

2.状态转移方程(类似于数学归纳法,由前面的数据根据一定的关系推出后面的数据)

1)如果有某一个字符串为空的话,f[i][j]=0,在这个是全局变量,初始化为0,不用特别考虑

2)如果a[i]=b[j],那么dh走一步,学妹也走一步,最长公共子序列的长度可以在原来的基础上+1,表示为:

if(a[i]==b[i]) f[i+1][j+1] = f[i][j - 1] + 1;

3)如果a[i]!=b[j],这时有两种选择,要么dh走一步,要么学妹走一步,又要求大,那么表示为:

f[i + 1][j + 1] = max(f[i][j + 1], f[i + 1][j]);

3.找出初始值

这里是全局变量,初始化为0。

7-7 有多少个质数 题目内容

给一个正整数 n ,你需要求出 1,2,3,…,n 这 n 个数字有多少个是质数。
质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。

输入格式

在一行中给出一个正整数 n (1<=n<=30,000,000)

输出格式:

在一行中输出一个数字,表示 1,2,3,…,n 有多少个数字是质数。

输入样例:

10

输出样例

4

我的代码
#includeusing namespace std;
#define int long long
int n,sum;
int jugde(int x)
{if(x<2)
        return 0;
    if(x==2||x==3)
        return 1;
    if(x%4!=1&&x%4!=3)
        return 0;
    for(int i=3; i*i<=x; i+=4)
    {if(x%i==0||x%(i+2)==0)
            return 0;
    }
    return 1;

}
signed main()
{cin>>n;
    for(int i=2;i<=n;i++)
    {if(jugde(i))
            sum++;
    }
    cout<
AC代码
#includeusing namespace std;
const int maxn=3e7+5;
bool su[maxn];
int primer[maxn];
int main()
{int n,sum=0;
    cin>>n;
    su[0]=su[1]=true;
    for(int i=2;i<=n;i++)
    {if(!su[i])
        {primer[sum++]=i;
            for(int j=2*i;j<=n;j+=i)
                su[j]=true;
        }
    }
    cout<
总结: 问题分析:

我用的是四倍筛,练习的时候还不知道埃氏筛,有两个测试点运行超时。

埃氏筛

主要原理:把已经判断过的素数存到primer中,并把素数的倍数全部标记成非素数。

这里也码一个佬对素数筛的总结
https://blog.csdn.net/Yuki_fx/article/details/115103663

注:如果两个数组都开成int的话内存超限,bool只占一个字节,而int占四个字节,这里bool数组也可以用char数组代替。

7-8 天上也会掉馅饼 题目内容

众所周知,天上是不会掉馅饼的。可是有一天,在一座城市的上空,一架装满馅饼的运输机在高空遇到了强烈的气流,为了保证运输机的安全,机长决定将一部分馅饼分散空投于某座小镇中。在小镇中的小明第一时间发现了天上在掉馅饼,于是他急忙准备接馅饼,他希望能尽可能多地接到馅饼。

小明当前位于一条道路之上,他可以从所在道路任意一点开始(从 0 秒开始),道路长度为 d 米(即可行走区域为[1,d])。天上一共会掉落 n 个馅饼,每个馅饼将于 t 秒后掉落于道路 x 米处,小明每一秒可以选择留在原地或者向前或者向后移动 1 米,求小明最多可接到多少馅饼?

由于小明也是个讲卫生的人,所以他并不会捡起掉在地上的馅饼。

这里我们将“能接到馅饼”定义为——当一个馅饼还有 0 秒掉到地面 x 米处时,如果小明此时正在该处,即可接到馅饼。

注意:可能会有多个馅饼在相同时间后落于同一地点。

输入格式

第一行给出两个整数 d,n。

接下来的 n 行,每行两个整数 x 和 t,代表第 i 个馅饼的状态(具体含义见题面描述)。

输出格式:

在一行中输出一个整数,为小明大可接到的馅饼数。

输入样例:

10 6
3 1
2 2
1 3
5 3
6 4
7 5

输出样例

4

AC代码
#includeusing namespace std;
#define int long long
const int N=1e3+5;
int dp[N][N],a[N][N];
signed main(){int n,d,mxt=0,maxn=0;
    cin>>d>>n;
    for(int i=1;i<=n;i++)
    {int x,t;
        cin>>x>>t;;
        a[t][x]++;
        mxt=max(mxt,t);
    }
    for(int i=mxt;i>=0;i--)
    {for(int j=1;j<=d;j++)
        {dp[i][j]=max(max(dp[i+1][j-1],dp[i+1][j]),dp[i+1][j+1])+a[i][j];
        }
    }
    for(int j=1;j<=d;j++)//开始时小明的位置不确定,所以要比较小明在不同位置开始能接到的馅饼数
        maxn=max(maxn,dp[0][j]);
    cout<
总结

这题我认为是一个典型数塔dp的一个小改编,这题的AC代码,是看了一个典型数塔dp题目的各种佬的文章,之后自己写的代码。

这里也码了我看过的文章
https://blog.csdn.net/qq_43765333/article/details/107100259

解题思路

1.设计状态(定义一个数组,确定其各维含义)

i表示时间为i,j小明所在的位置,dp[i][j]表示i时间,小明j位置时,小明接到的馅饼的数量。

2.状态转移方程(类似于数学归纳法,由前面的状态,根据一定的关系推出后面的状态)

小明每次移动有三种情况:1)原地不动;2)前走一步;3)后走一步。只要把小明移动前接到的大馅饼数,加上移动后i时间掉在j位置上的馅饼数,就是小明在i时间,j位置上,接到的大馅饼数。

dp[i][j]=max(max(dp[i+1][j-1],dp[i+1][j]),dp[i+1][j+1])+a[i][j];

3.找出初始值
这里是全局变量,初始化为0。

7-9 遍遍遍历 题目内容

Keven这次遇到了一个大麻烦,题目大意是给你一个二叉树的前序遍历和中序遍历,输出它的后序遍历,这可难坏了Keven,还好Keven认识你,于是他向你请教了这个问题。

输入格式

第一行一个数字,表示前序和中序序列的长度。

第二行一个字符串,表示它的前序遍历序列

第三行一个字符串,表示它的中序遍历序列。

保证字符串中只含有大写字母并且互不相等

输出格式:

在一行中输出它的后序遍历。

输入样例:

4
ABCD
BACD

输出样例

BDCA

AC代码1
#includeusing namespace std;
#define int long long
void retree(string a,string b)
{int t = b.find(a[0]);//找根节点在b中的位置
	if (t != 0)//如果这个根节点还有叶节点
		retree(a.substr(1, t), b.substr(0, t));//对左叶的树进行操作
	if (b.size() >t + 1)//如果这个根节点有右子叶
		retree(a.substr(t + 1), b.substr(t + 1));
	cout<< a[0];//输出节点代表的信息
    return ;
}
signed main()
{int n;
    cin>>n;
    string q,z;
    cin>>q>>z;
    retree(q,z);
    cout<<'\n';
    return 0;
}
AC代码2
#include#includeusing namespace std;
#define int long long
struct TNode{char data;
    TNode *lchild,*rchild;
};
typedef TNode *BinTree;
BinTree pre_mid_build(char* pre, char* mid, int num){if(pre==NULL||mid==NULL||num<=0)
        return NULL;

    BinTree root=new TNode;
    root->data=pre[0];
    root->lchild=NULL;root->rchild=NULL;

    if(num==1)  return root;

    int left_num=0;//左子树结点总数
    char* middle_root=mid;

    while(*middle_root!=pre[0]&&middle_root<=(mid+num-1)){middle_root++;
        left_num++;
    }

    if(left_num>0)//创建左子树
        root->lchild=pre_mid_build(pre+1,mid,left_num);
    if(num-left_num-1>0)//创建右子树
        root->rchild=pre_mid_build(pre+left_num+1,mid+left_num+1,num-left_num-1);
    return root;
}

void PostorderTraversal(BinTree T){//后序遍历
    if(T) {PostorderTraversal(T->lchild);
        PostorderTraversal(T->rchild);
        cout<< T->data;
    }
    return ;
}
void DestroyBiTree(BinTree &T){//销毁二叉树
    if(T) {DestroyBiTree(T->lchild);
        DestroyBiTree(T->rchild);
        delete T;
        T = nullptr;
    }
    return ;
}
signed main(){int n;
    cin>>n;
    char pre[n+5];
    char mid[n+5];
    cin>>pre>>mid;
    BinTree root=pre_mid_build(pre, mid, n);
    PostorderTraversal(root);
    DestroyBiTree(root);
    cout<<'\n';
    return 0;
}
总结

这题本意应该是前序遍历和中序遍历重构二叉数,然后输出后序遍历。AC代码2就是这样写的,是我根据《数据机构》和佬的文章写的

佬的文章码在这
https://blog.csdn.net/weixin_65908362/article/details/127721109

我在网上冲浪的时候看到一个另一个佬的优化代码,我觉得很巧妙,这个AC代码1就是佬的代码。

佬的文章也码在这里
https://blog.csdn.net/qq_62658309/article/details/127742327

解题思路

这题目的还是比较明确的,重构二叉树的递归思路是比较好找,就是码出来比较不容易。AC代码1直接看比较难理解,画出树,根据代码模拟,比较好理解。

7-10 无间道 题目内容

Bear_2 发现春天花花幼儿园中出了内鬼。

如果一个人满足下面两个的条件,那么就可以认定他为内鬼:
1、所有人对他都是信任的
2、他对所有人都是不信任的

Bear_2 开始调查幼儿园的情况,他发现幼儿园中总共有 n 个人,他每调查出两个人的关系就会记到小本本上,现在共找出了 m 对关系,请问可以找到几个内鬼。

输入格式

第一行给出两个正整数 n,m(1<=n,m<=10
6
) 分别表示春天花花幼儿园的人数和两人之间的关系。

之后的 m 行,每行给出两个正整数 a,b(1<=a,b<=n,a!=b) 表示 a 信任 b 。

由于 Bear_2 比较蠢可能会重复调查两个人的关系并且记录。

输出格式:

第一行输出一个正整数 k 表示内鬼的数量。如果没有内鬼则输出 0
第二行从小到大输出 k 个正整数表示内鬼的编号。

输入样例:

3 5
1 2
1 3
2 1
2 3
2 1

输出样例

1
3

我的代码(不是正确的代码)
#includeusing namespace std;
#define int long long
int a[1000005],b[1000005],c[1000005];
bool cmp(int a,int b)
{return aint n,m,k=0;
    cin>>n>>m;
    //a表示信任的人数,b表示被信任的人数
    while(m--)
    {int x,y;
        cin>>x>>y;
        a[x]++;
        b[y]++;
    }
    for(int i=1;i<=n;i++)
    {if(a[i]==0||b[i]==n)
            c[k++]=i;
    }
    cout<
AC代码
#includeusing namespace std;
#define int long long
set>s;//存n个人之间的关系,由于set中没有重复数据的特性,将重复数据过滤
setans;//把内奸的存起来,set中能自动排序
signed main()
{int n,m,q,sum=0;
    cin>>n>>m;
    vectorsum1(n+5,0);//sum1[i]表示i信任多少人
    vectorsum2(n+5,0);//sum2[i]表示i被多少人信任
    
    while(m--)
    {int a,b;
        cin>>a>>b;
        s.insert({a,b});//因为有重复数据,所以不能在输入的时候直接计数
    }
    
     set>::iterator it1;//迭代器,用于遍历set
     for(it1=s.begin();it1!=s.end();it1++)
     {sum1[it1->first]++;
        sum2[it1->second]++;
     }
       
     for(int i=1;i<=n;i++)
        if(sum1[i]==0&&sum2[i]==n-1)//满足题目给出的内奸条件的,存入ans
        {ans.insert(i);
            sum++;
        }
        
    cout<::iterator  it;
    for(it=ans.begin();it!=ans.end();it++)
        cout<<*it<<'\n';
    return 0;
}
总结 问题分析

我的代码虽然过了全部的测试点,但是不是正确的代码。我把题目的两个条件,理解成满足其一即可,而且我也没有处理重复记录的情况,只能说是撞大运了。

解题思路

由题目的“由于 Bear_2 比较蠢可能会重复调查两个人的关系并且记录”,比较容易想到用set容器来实现去重,实现了去重的话,这个题目就没有其他难点了。答案存储也可以直接用数组来存储,数据本身就是有序的,但是不能直接输出,因为要先统计间谍的数量(如果有其他的方法欢迎随时踢我)。

7-11 简单的图 题目内容

有一个 n 个点 m 条边的无向不一定联通图。现在 Bear_2 想知道一对点 (x,y) 和多少条边相连,也就是说共有多少条边连接点 x 或者点 y 。他一共会问 q 次,请你回答他的询问。

输入格式

第一行给出两个正整数 n,m(1<=n,m<=10
6
)

之后的 m 行,每行给出两个正整数 u,v(1<=u,v<=n) 表示点 u 和点 v 之间有一条无向边。保证没有自环,但可能有重边。

之后的一行给出一个正整数 q(1<=q<=10
5
) 表示询问的次数

之后的 q 行,每行给出两个正整数 u,v(1<=x,y<=n) 表示询问点 x,y 和多少条边相连。

输出格式:

对于每次询问在一行内输出一个正整数 k 表示有 k 条边和点 x,y 相连。

输入样例:

4 5
1 2
1 3
2 3
2 4
2 1
5
1 2
1 3
1 4
2 3
2 4

输出样例

5
4
4
5
4

AC代码
#includeusing namespace std;
#define int long long
const int N=1e6+5;
vectortu[N];
map,int>c;
signed main()
{int n,m;
    cin>>n>>m;
    while(m--)
    {int u,v;
        cin>>u>>v;
        tu[u].push_back(v);
        tu[v].push_back(u);
        c[{u,v}]++;
    }
    int k;
    cin>>k;
    while(k--)
    {int x,y;
        cin>>x>>y;
        if(x==y)
            cout<x,y}]-c[{y,x}]<<"\n";//c[{x,y}]和c[{y,x}]在图上表示相同的边,且都存在重复的情况
    }
    return 0;
}
总结 解题思路

有佬说过,“图的难点就在图的构建”。我的代码是开了二维的vector,果不其然,内存超限。然后有佬分享了代码,这个AC代码是看了佬的代码之后写的,跟佬的有一点点不一样。

1)因为这个图是无向图,因为u ,v相连,所以u点到v点有边,v点到u点有边,在tu[u]中插入v,tu[v]中插入u,tu[i].size()表示tu[i]中有多少个元素,即i点有多少条边;

2)如果x,y相连,有的边会被计数两次,所以用c[{u,v}]来存u->v的边的数量

第二场

共11题,AC6题,最后两题目前为止还不知道咋整。涉及知识点:字符串、模拟、逆元、快速幂、贪心、并查集

7-6 YooQ和olderciyuan玩石子 题目内容

YooQ 和 olderciyuan 来到湘潭大学参(gong)加(费)比(lv)赛(you),湘潭大学的门口有很多堆石子,于是童心大起的两人玩起了堆石子游戏,他们想将 N 堆石子合成一堆,合并两堆的代价为两堆石头的数量和,那么现在问题来了, 如果才能以最小的代价合成石子?

输入格式

第一行给出一个整数 T(1<=T<=10),代表共有 T 组输入数据。

接下来 T 行,每行给出一个一个整数 N(1<=N<=1e6),随后给出 N 个正整数 a1,a2,a3…an(1<=ai<=1e9),代表每堆石子的石子个数。

题目保证所有输入数据 N 的总和不超过 2e6 。

输出格式:

对于每一组输入数据,输出一个整数,代表最小代价。

输入样例:

3
1 1
3 1 2 3
3 1 1 1

输出样例

0
9
5

AC代码
#includeusing namespace std;
#define int long long

signed main()
{int t;
    cin>>t;
    while(t--)
    {priority_queue,greater>q;//优先队列,top是最小值
        int n,sum=0,sum1=0;
        cin>>n;
        
        while(n--)
        {int x;
            cin>>x;
            q.push(x);
        }
        
        while(q.size()>1)//只剩一堆石子的时候结束循环
        {sum=q.top();
            q.pop();
            sum=sum+q.top();
            q.pop();
            q.push(sum);//把石子合并后入队,并排序
            sum1+=sum;
        }
        
        cout<
总结 问题分析

这题比较明显,一眼贪心,把石子从小到大排序,先把小的合并。练习的时候,我排序后就直接合并,然后只过了少数测试点。快结束的时候,我才发现,合并了两堆石子后,形成了新的石子堆,要再次排序,将最小的两个合并。
注:
这里不建议每次合并后又用sort排序。因为快排在数据比较有序的情况下,时间复杂的堪比冒泡排序(O(n^2))。
这里有一个小技巧,有时候题目给的数据可能比较有序,但是,你又需要将它排序,你可以先把它打乱,然后再排序。这样可能会更快,洛谷这个题就是一个例子亲测直接用sort会T)
https://www.luogu.com.cn/problem/P1177

解题思路

分析清楚之后,就比较容易了,可以用优先队列来实现。每次把队头的两个元素取出来,相加后,把它们的和入队,一直循环到只剩下一堆石子。

注意

我一开始把优先队列定义在全局,导致每次运行后都把上一次的结果保留,浪费了很多时间来debug。

7-7 霸道 题目内容

有道是先来后到,后来霸道。在青青草原排队吃饭,只要前面的人战斗力不如你,你就可以让他直接离开。新来的人会先赶走战斗力不如他的人,然后再开始排队。

Bear_2 拿到了一份排队的记录,有 n 个人来吃饭,按顺序将来店里吃饭的人编号为 1 到 n ,第 i 个人的战斗力为 Di 。每当排队人数大于 2 人时,队列的第一个人就可以吃到饭,然后离开。

请从小到大输出吃到饭的人物编号。

输入格式

第一行给出一个正整数 n(1<=n<=1e5) ,表示来吃饭的人的数量之后的 n 行,第 i 行给出一个正整数Di(1<=Di<=1e9) 表示编号为 i 的人的战斗力

输出格式:

第一行输出一个正整数表示吃到饭的人的数量 K

第二行从小到大输出 K 个正整数表示吃到饭的人的编号。(末尾没空格)

输入样例:

7
5
4
3
6
7
1
1

输出样例

2
1 5

AC代码
#includeusing namespace std;
#define int long long
int n,i,j=1;
deque>q;
vectora(1e5+1,0);
signed main() 
{cin>>n;
    deque>::iterator it=q.end();
    while(n--)
    {++i;
        int d;
        cin>>d;
        it=q.end()-1;
        while(!q.empty()&&d>it->second)//要先判断队列是否为空
        {q.pop_back();
            it=q.end()-1;
        }
        q.push_back({i,d});
        
        if(q.size()>=3)//队列中人数大于2时,第一个人吃饭
        {it=q.begin();
            a[j++]=it->first;//把第一个人的序号存到a中
            q.pop_front();//把第一个元素弹出
        }
    }
    
    cout<
总结 问题分析

练习的时候一直段错误,我一开始以为是迭代器跑来跑去,后面用其他方法写的时候还是段错误。求助了一下佬,发现是while循环的条件逻辑上有问题。

解题思路

因为这里要把武力值不如自己的人赶走,所以要用deque,选好容器后,就按题意模拟。要注意q.end()不是指向最后一个元素,而是最后一个元素的后一个位置,所以我让it=q.end()-1。

注意

这里我控制输出格式用的是

for(int i=1;i

是一个小技巧,当满足[ ]中的条件为真,输出后面的字符,条件为假,输出前面的字符。

7-9 WaWa机 题目内容

在学校 D 栋的一个小隔间里,隐藏着一个神奇的 WaWa 机。小隔间只有在星期天的时候才会开门!为什么叫 WaWa 机呢?因为在集训队的队员们囤积了一星期的 Wa 题次数后,能以去小隔间抓相同次数的 WaWa。 但是 YooQ 不想让大家拿走 WaWa,也就是说不能拿走 WaWa,只能抓个开心。

WaWa 机里有 N 个娃娃,从左到右依次摆放。每次抓取只能从左向右地将某个右边的 WaWa 抓取到左边,只有当“抓的 WaWa 的高度 + 当前经过 WaWa 的高度<= WaWa 机的高度”才能通过当前 WaWa,从而将这个 WaWa 抓取到左边。

队员们想把小的 WaWa 尽量挪到前面(也就是左边)。现在告诉你 N 个 WaWa 的摆放情况以及一个数 H,表示 WaWa 机的高度。

请你输出当队员们完成任务时,WaWa 机里的 WaWa 的高度序列。(从左到右)

输入格式

在第一行中输入一个整数 T,表示有 T 组测试数据。(1<=T<=10)

接下来对于每组输入数据,先于第一行给出两个整数 N 和 H,N 表示有 N 个 WaWa,H 表示当前 WaWa 机的高度。(1<=N<=5e3,1<=H<=1e8)

再于第二行给出 N 个整数 a1,a2…an,ai表示原来 WaWa 机里面第 i 个 WaWa 的高度。(1<=ai<=H)

输出格式:

对于每组数据,在一行中输出一行数字表示当队员们完成任务时,WaWa 机里的 WaWa 的高度序列。数字间以空格分割,且行末没有多余空格。

输入样例:

3
8 10
5 1 2 9 2 8 5 2
5 10
4 5 3 2 1
5 8
7 6 5 4 2

输出样例

1 2 5 9 2 2 8 5
1 2 3 4 5
7 2 6 5 4

AC代码
#includeusing namespace std;
#define int long long
signed main()
{int t;
    cin>>t;
    while(t--)
    {int n,h,flag=1;
        cin>>n>>h;
        int a[n+1];
        
        for(int i=0;i>a[i];
        while(flag)
        {flag=0;
            for(int j=n-1;j>0;j--)
            {if(a[j]+a[j-1]<=h&&a[j]flag++;
                    swap(a[j],a[j-1]);
                }
            }
        }
        for(int i=0;i
总结 问题分析

练习的时候被这个题目吓到了,可能脑子也不太清醒了。后面补题的时候,仔细看了一下,又求助了一下佬,发现是有点类似冒泡排序。

解题思路

因为要把小的数字尽可能的放到前面,所以可以从最后一个wawa开始遍历,把相邻的可以交换位置的娃娃全部交换位置,这个算法的时间复杂的是O(n^2),果然超时了。

因为我每次循环都全部遍历,把能交换位置的相邻wawa全部交换,所以如果某次循环中,没有wawa交换了位置,那么说明现在的位置已经是最终结果了,这时候就可以跳出循环,所以我加了一个flag记录某次循环wawa交换位置的次数。

写在后面

感觉我某些题目的方法不是特别好,如果有其他的解题方法,欢迎随时赐教。

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


当前名称:寒假第一、二场合集-创新互联
URL地址:http://jkwzsj.com/article/ediji.html