A.先交换
思维:给你一个数组和一种无限次数的操作,问你操作多少次能把a1变成奇数
做法:根据题意模拟即可,只有三种可能 要么 为0 要么为 1 要么不存在
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
using namespace std;
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define sz(a) (int) (a).size()
#define endl "\n"
void solved() {
int n;
cin>>n;
vector<int> a(n+1);
int idx=-1;
for(int i=1;i<=n;i++){
cin>>a[i];
}
if(a[1]%2==1){
cout<<0<<endl;
return ;
}
for(int i=2;i<=n;i++){
if(a[i]<a[1]&&a[i]%2==1){
idx=i;
break;
}
}
if(idx>1){
cout<<1<<endl;
}
else{
cout<<-1<<endl;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--) {
solved();
}
return 0;
}
B.再交换
思维/构造 思路:只需要逐位对比A,B,第一次位数不同时,如果A大于B那么交换A和B的这一位,如果B大于A那么直接交换第一位或者最后一位(要注意相等的位置不能在这二位还取这二位)
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
using namespace std;
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define sz(a) (int) (a).size()
#define endl "\n"
void solved() {
int n;
cin>>n;
string a,b;
cin>>a>>b;
for(int i=0;i<n;i++){
if(a[i]!=b[i]){
if(b[i]>a[i]){
if(i>0){
cout<<i-1+1<<" "<<i-1+1<<endl;
}
else cout<<i+1+1<<" "<<i+1+1<<endl;
return ;
}
else{
cout<<i+1<<" "<<i+1<<endl;
return ;
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--) {
solved();
}
return 0;
}
C.空洞骑士
思维/贪心:
可以明确一点,初始位置s只可能在三种地方,第一个金币左边,最后一个金币右边,或者在中间为最优的,根据题意讨论即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
using namespace std;
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define sz(a) (int) (a).size()
#define endl "\n"
void solved() {
int n;
cin>>n;
string a,b;
cin>>a>>b;
for(int i=0;i<n;i++){
if(a[i]!=b[i]){
if(b[i]>a[i]){
if(i>0){
cout<<i-1+1<<" "<<i-1+1<<endl;
}
else cout<<i+1+1<<" "<<i+1+1<<endl;
return ;
}
else{
cout<<i+1<<" "<<i+1<<endl;
return ;
}
}
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--) {
solved();
}
return 0;
}
D.障碍
枚举优化:
思路:很容易想到的一种思路是枚举x,然后将其对每一个隔壁进行计算。可以想到的是x最多只有500,所以考虑枚举x对于每个隔壁的值,最后取最大即可
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
using namespace std;
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define sz(a) (int) (a).size()
#define endl "\n"
void solved() {
int n,m;
cin>>n>>m;
vector<int> a(m+2);
for(int i=1;i<=m;i++){
cin>>a[i];
}
a[m+1]=n;
LL ans=1;
for(int i=0;i<=m;i++){
for(int j=0;j<=500;j++){
int r=i+j+1;
if(r>m+1) break;
LL res=a[r]-a[i]-j*j;
ans=max(ans*1LL,res);
}
}
cout<<ans<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
solved();
return 0;
}
E.生成树与路径
图论/构造:
首先来说最小生成树和最短路路是容易确定的,就是从1到n进行线性连接即可,关键是如何满足在加边的情况下仍然保留他们
考虑如何破坏最短路:当1不通过到 2,3,4,....i-1时的距离大于直接到i的距离时那么最短路就会被破坏,所以我们从小开始考虑,1 到 3 ,2 到 4,3 到 5.,1 到 4 2 到 5....这样的距离,贪心的考虑,因为间隔点越多需要的边就越长,所以我们把短边用在相隔点较少的地方,把长边用在点较多的地方
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
using namespace std;
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define sz(a) (int) (a).size()
#define endl "\n"
void solved() {
int n,m;
cin>>n>>m;
int i=1;
int t =1;
while(i<=m){
for(int j=1;j<n;j++){
if(j+t>n||i>m) break;
cout<<j<<' '<<j+t<<' '<<i++<<endl;
}
t++;
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int t;
cin >> t;
while (t--) {
solved();
}
return 0;
}
F.球球大作战:
贪心+二分答案
1.通过模拟过程可以发现,从最大值依次比到最小值是最优的
2.如果X可以,那么大于X的一定可以,具有单调性,我们考虑二分答案
那么时间复杂度就是O(nlogn)的
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int, int> PII;
using namespace std;
#define rall(x) (x).rbegin(), (x).rend()
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define sz(a) (int) (a).size()
#define endl "\n"
const int N=1e5+10;
LL a[N],b[N];
int n;
bool check(LL x){
LL minn=a[n];
for(int i=n-1;i>=1;i--){
if(i!=x) minn=(minn+a[i])/2;
}
return a[x]>=minn;
}
void solved() {
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i],b[i]=a[i];
sort(a+1,a+n+1);
int l=1,r=n;
while(l<r){
LL mid=(l+r)>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
string ans="";
for(int i=1;i<=n;i++){
if(b[i]>=a[l]) ans+='1';
else ans+='0';
}
cout<<ans<<endl;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
solved();
return 0;
}
总结:
1.在求解问题时,考虑暴力优化 ,注意观察问题的性质能否给题目带来化简
2.当你觉得题目很难时,或者没用思路时,可以看看自己是不是把题目想复杂了,可以考虑暴力或者手算样例积攒思路