24暑假集训day1下午
下午
内容:二分分治模拟
广告:推荐此题单
1. 二分
二分查找
优点:在检验一个元素之后可以很快的舍弃掉一
半的元素,从而快速锁定目标元素。
问题简述:输入
思路:
直接二分查找
std:
#include <iostream>
#define int long long
#define endl '\n'
using namespace std;
const int MAXN = 1e6 + 10;
int a[MAXN];
signed main(){
int n, m;
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> a[i];
}
for(int i = 1;i <= m;i++){
int x;
cin >> x;
int l = 1, r = n;
while(l < r){
int mid = (l + r) / 2;
if(a[mid] >= x){
r = mid;
} else {
l = mid + 1;
}
}
if(a[l] != x){
cout << "-1 ";
} else {
cout << l << " ";
}
}
return 0;
}
二分答案
用处:有最大值最小或者最小值最大的描述时可以尝试考虑二分答案 (反正你感觉很怪就对了)
问题简述:给你一排
思路:
直接二分查找
std:
#include<bits/stdc++.h>
using namespace std;
int l , n , m;
int a[100010];
bool check(int d) {
int last = 0 , cnt = 0;
for(int i = 1 ; i <= n ; i ++) {
if(a[i] - last < d) cnt ++;
else last = a[i];
}
if(l - last < d) cnt ++;
return cnt <= m;
}
int main() {
scanf("%d%d%d", &l , &n , &m);
for(int i = 1 ; i <= n ; i ++) {
scanf("%d" , &a[i]);
}
int le = 1 , r = l + 1 , mid;
while(le + 1 < r) {
mid = (le + r) / 2;
if(check(mid)) le = mid;
else r = mid;
}
printf("%d", le);
return 0;
}
2. 分治
本质:分而治之
问题简述:组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有
思路:
std:
#include <iostream>
using namespace std;
const int MAXN = 1e6 + 10;
int a[MAXN];
int L, n , m;
bool check(int d){
int last = 0, cnt = 0;
for(int i = 1;i <= n;i++){
if(a[i] - last < d) cnt++;
else last = a[i];
}
if(L - last < d){
cnt++;
}
return cnt <= m;
}
int main(){
scanf("%d%d%d", &L , &n , &m);
for(int i = 1;i <= n;i++){
scanf("%d", &a[i]);
}
int l = 1 , r = L + 1 , mid;
while(l + 1 < r){
mid = (l + r) / 2;
if(check(mid)){
l = mid;
}
else{
r = mid;
}
}
printf("%d", l);
return 0;
}
问题简述:对于给定的一段正整数序列,逆序对就是序列中
思路:
只要出现右侧的值<左侧的值的情况,就出现了逆序对。左侧还剩多少个值,就会出现多少个逆序对。
再把所有分治时出现的所有逆序对的个数加起来就行了
std:
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN = 500005;
int d[MAXN];
int a[MAXN],b[MAXN],c[MAXN];
int ans = 0;
void merge(int n,int m){
int aa = 1,bb = 1;
int cc = 0;
while(aa <= n && bb <= m){
if(a[aa] <= b[bb]){
cc ++;
c[cc] = a[aa];
ans += bb - 1;
aa ++;
}
else{
cc ++;
c[cc] = b[bb];
bb ++;
}
}
while(aa <= n){
cc ++;
c[cc] = a[aa];
ans += bb - 1;
aa ++;
}
while(bb <= m){
cc ++;
c[cc] = b[bb];
bb ++;
}
}
void guibing(int l,int r){
if(l >= r){
return;
}
int mid = (l+r)/2;
guibing(l,mid);
guibing(mid+1,r);
for(int i=l;i<=mid;++i){
a[i - l + 1] = d[i];
}
for(int i=mid+1;i<=r;++i){
b[i - mid] = d[i];
}
merge(mid - l + 1,r - mid);
for(int i=l;i<=r;++i)
d[i] = c[i - l + 1];
}
signed main(){
int n;
scanf("%lld",&n);
for(int i=1;i<=n;++i){
scanf("%lld",&d[i]);
}
guibing(1,n);
printf("%lld",ans);
}
3. 模拟
本质:按照题目的要求进行模拟操作
std:
#include<iostream>
using namespace std;
int a[100000], b[100000], g[100000], k[100000];
int main(){
int x, y, n ,s=-1;
cin >> n;
for(int i = 0;i < n;i++){
cin >> a[i] >> b[i] >> g[i] >> k[i];
}
cin >> x >> y;
for(int i = 0;i < n;i++){
if(x >= a[i]&&y >= b[i]&&x <= a[i] + g[i]&&y <= b[i] + k[i]){
s = i + 1;
}
}
cout << s;
}
std:
#include<cstdio>
using namespace std;
int w[10001], s[101], maxx;
int main(){
int n, m;
scanf("%d%d",&n,&m);
for (int i = 1;i <= n;i++){
scanf("%d", &w[i]);
}
for (int i = 1;i <= n;i++){
maxx = 1;
for (int j = 2;j <= m;j++)
if (s[maxx] > s[j]){
maxx = j;
}
s[maxx] += w[i];
}
maxx = 1;
for (int i = 1;i <= m;i++){
maxx = s[i] > maxx ? s[i] : maxx;
}
printf("%d",maxx);
}
问题简述: 简述不了
std:
#include <bits/stdc++.h>
using namespace std;
int N, a[40][40], h, l;
int main(){
cin >> N;
a[0][N/2] = 1, h = 0, l = N / 2;
for(int i = 2;i <= N * N;i++){
if(h==0&&l!=N-1) a[N-1][l+1]=i,h=N-1,l++;
else if(l == N - 1&&h != 0) a[h - 1][0] = i,h--, l = 0;
else if(h == 0&&l == N - 1) a[h + 1][l] = i,h++;
else if(h != 0&&l != N - 1){
if(a[h - 1][l + 1] == 0&&h - 1 >= 0&&l + 1 <= N){
a[h - 1][l + 1] = i;
h--;
l++;
}
else a[h + 1][l] = i, h++;
}
}
for(int i = 0;i < N;i++){
for(int j = 0;j<N;j++){
cout << a[i][j] << ' ';
}
cout << endl;
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步