模拟./
题目意思:
给定n,s两个数,随后再给出n个坐标,要求从s开始遍历到每一个坐标走的最短路径,可以在某个坐标向左或者向右走动。
思路:
给定的s就两条路可以走,一条是向右边走到头,一条是向左边走到头,随后再回头走。
特判s在最左边或者最右边的情况,n=1的特殊情况也给出特判。
#include<bits/stdc++.h>
using namespace std;
void solve(){
int n, s;
cin >> n >> s;
vector<int> x(n);
for (int i = 0; i < n; ++i) {
cin >> x[i];
}
if (n == 1) {
cout << abs(x[0] - s) << endl;
return;
}
if (s <=x[0]) {
cout << x[n-1]- s << endl;
} else if (s >= x[n-1]) {
cout << s - x[0]<< endl;
} else {
int answer = (x[n-1] - s) * 2 + (s - x[0]);
//左边
int cnt = (s - x[0]) * 2 + (x[n-1] - s);
//右边
cout << min(answer, cnt) << endl;
}
}
signed main() {
int t;
cin >> t;
while (t--) {
solve();
}
}
思维./
题目思路:
给定一个字符串,判断能否找出a,b,c三个字符串,使得a+b+c=该字符串且b是a+c的字串。
思路:
首先我们要从字串入手,b的最好状态就是一个字母,这样我们可以最大可能的满足b是a+c的字符串这一条。
而a,c我们可以认为分别从该字符串的头和尾不断的取字母,也就是说,a,c最短的情况下是取给出字符的头和尾。
于是我们可以开一个map存储给定字符串每一个字母出现的次数,随后从第二个字母开始遍历到倒数第二个字母,观察遍历的字母出现的次数是否大于等于2。
根据上述我们就可以判断该字母是否可能成为a+c的字串,此时b就是该字母,这是最优解法。
#include<bits/stdc++.h>
using namespace std;
void solve() {
int n;cin>>n;
string ac;cin>>ac;
map<char,int>p;
for(auto it:ac){
p[it]+=1;
}
for(int i=1;i<ac.size()-1;i++){
if(p[ac[i]]>=2){
cout<<"YES"<<endl;
return;
}
}
cout<<"NO"<<endl;
return;
}
int main() {
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
模拟./
题目意思:
给定一个矩阵,在进行一次操作(假设在选定在(i,j)这个坐标上,那么i行j列所有数字都减去1)之后,判断该矩阵中的最大值。
思路:
首先我们要知道答案一定是该矩阵中的最大值或者最大值减去1。
故我们只要找到是否存在一种操作可以将该矩阵中的最大值全部去掉就行,若是可以,答案就是最大值减去1,若不是就是最大值。
由于题目给出我们提示,我们可以开两个行列的数组,如果在(i,j)上发现最大值,就对该行和列进行++,表示这一行和这一列最大值的个数,并统计最大值出现的个数。
最后我们从头到尾进行遍历,每次遍历都判断(i,j)i行和j列中所有的最大值是否等于出现的个数,如果满足,则存在一种操作可以使得最大值全部消失,此时直接输出最大值-1。反之输出最大值。
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n,m;cin>>n>>m;
int a[n+1][m+1];
int k=-1;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
k=max(k,a[i][j]);
}
}
vector<int>r(n+1,0);
vector<int>l(m+1,0);
int sum=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(a[i][j]==k)r[i]++,l[j]++,sum++;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
int z=a[i][j]==k?1:0;
//这里对行列的交叉点进行特判是否为最大值
if(sum==r[i]+l[j]-z){
cout<<k-1<<endl;
return ;
}
}
}
cout<<k<<endl;
return ;
}
signed main(){
int t;cin>>t;
while(t--)solve();
}
题目意思:
给定a,b数组,你可以进行以下三次操作:
1.选择一个索引交换a(i)和a(i+1)的值
2.选择一个索引交换b(i)和b(i+1)的值
3.选择一个索引交换a(i)和b(i)的值
操作之后要满足a(i)<a(i+1)这种情况。
如果要交换 ai 和 ai+1 的值,输出两个整数1和 i。注意 1≤i<n。
如果要交换 bi 和 bi+1 的值,输出两个整数2和 i。注意 1≤i<n。
如果要交换 ai 和 bi 的值,输出两个整数3和 i。注意 1≤i≤n。
思路:
直接对a,b数组进行暴力遍历,若是看到满足条件的情况就直接放入到数组中,最后全部输出。
#include<bits/stdc++.h>
using namespace std;
#define int long long
void solve(){
int n;cin>>n;
vector<int>a(n+1);
vector<int>b(n+1);
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<=n;i++)cin>>b[i];
vector<pair<int,int>>p;
for(int i=1;i<=n;i++){
for(int j=1;j<=n-i;j++){
//冒泡排序
if(a[j]>a[j+1]){
//左边大于右边的情况下
swap(a[j],a[j+1]);
p.push_back({1,j});
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n-i;j++){
//冒泡排序
if(b[j]>b[j+1]){
swap(b[j],b[j+1]);
p.push_back({2,j});
}
}
}
for(int i=1;i<=n;i++){
if(a[i]>b[i]){
p.push_back({3,i});
}
}
cout<<p.size()<<endl;
for(auto answer:p){
cout<<answer.first<<" "<<answer.second<<endl;
}
}
signed main(){
int t;cin>>t;
while(t--)solve();
}
题目意思:
新定义f(a,b)为a和b中数字相同的位置数,例如f(12,21)=0,f(31,37)=1。在l到r之间找到x使得f(l,x)+f(x,r)最小。
思路:
我们不妨列举出两个案例:
6 7此时x只能取6或者7,那么答案就只能是1
46 47 此时x只能取46或者47,此时答案是2+1或者1+2
546 547按照上述的规律,此时答案就是4+1或者1+4
于是我们不妨从后往前看l,r这两个数字,如果l和r相差1那么答案的贡献就加1,如果相同就加2,反之就不加。
注意我们这里的条件是找到最小值,所以对于x有很多种情况下,一定存在最大值。这个时候我们就直接对l,r的每一位进行判断即可。(找最大值)
#include <bits/stdc++.h>
using namespace std;
#define ll long long
void solve() {
int l, r;
cin >> l >> r;
int answer = 0;
while (r > 0) {
if (r - l == 1) {
answer++;
} else if (r == l) {
// 如果 r 和 l 相等,说明在某一位上 l 和 r 相同
answer += 2;
}
// 去掉 l 和 r 的最后一位数字
r /= 10;
l /= 10;
}
cout <<answer<< endl;
}
int main() {
ll t;
cin>> t;
for (int i = 1; i <= t; i++) {
solve();
}
return 0;
}