结构体排序,双指针,单调栈

结构体排序:

题目:Aki的行程

cpp 复制代码
### 描述
Aki 记录了训练营的若干个活动时间段。每个时间段用两个整数l,r表示(包含端点),含义是从第l天到第r天都有活动。
为了做一个更清晰的日程表,Aki 想把有交集或首尾相接的时间段合并:
- 若两个时间段[l₁, r₁]与[l₂, r₂]满足l₂ ≤ r₁ + 1(在按起点排序后),则它们可以合并为[l₁,max(r₁, r₂)]。
请输出合并后的所有时间段(按起点从小到大)。
---
### 输入描述
第一行一个整数m,表示时间段数量。
接下来m行,每行两个整数l,r。
- \( 1 \leq M \leq 10^5 \)
- \( 1 \leq L, R \leq 10^9 \)

---
### 输出描述
第一行输出合并后时间段的个数t。
接下来t行,每行输出一个合并后的时间段(按L从小到大)。

---
### 用例输入 1
```
5
1 3
8 10
2 6
7 7
15 18
```
### 用例输出 1
```
2
1 10
15 18
```

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll m,sum,num;
struct node{
    ll l,r;
}a[N],b[N];
bool cmp(node a,node b){
    return a.l<b.l;
}
int main(){
    cin>>m;
    for(int i=1;i<=m;i++){
        cin>>a[i].l>>a[i].r;
    }
    sort(a+1,a+m+1,cmp);
    for(int i=1;i<=m-1;i++){
         if(a[i+1].l<=a[i].r+1){
             a[i+1].l=a[i].l;
             a[i+1].r=max(a[i].r,a[i+1].r);
        }else{
             b[++num].l=a[i].l;
             b[num].r=a[i].r;
             sum++;
         }
    }
    b[++num].l=a[m].l;
    b[num].r=a[m].r;
    sum++;
    cout<<sum<<endl;
    for(int i=1;i<=sum;i++){
        cout<<b[i].l<<' '<<b[i].r<<endl;
    }
    return 0;
}

题目:Aki的活动选择

cpp 复制代码
### 描述
Aki 看到训练营里有很多活动,每个活动占用一个时间段 `[s_i, e_i]`(包含端点)。Aki 想参加尽可能多的活动,但同一时间只能参加一个活动。
如果 Aki 选择了一组活动,其编号依次为 `p₁,p₂,...`(按参加顺序),则需要满足:
- 对任意相邻两个活动 `p_j,p_{j+1}`,有 `s_{p_{j+1}} ≥ e_{p_j}`。
请你输出 Aki 最多能参加多少个活动。

---

### 输入描述
第一行一个整数 `n`,表示活动数量。
接下来 `n` 行,每行两个整数 `s_i, e_i`。
- \( 1 \leq n \leq 10^5 \)
- \( 0 \leq s_i, e_i \leq 10^9 \)

---

### 输出描述
输出一个整数,表示最多能参加的活动数量。

---

### 用例输入 1
```
6
1 3
3 5
0 2
5 6
2 4
6 7
```

### 用例输出 1
```
4
```

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll n,sum=1;
struct node{
    ll s,e;
}a[N];
bool cmp(node a,node b){
    if(a.e!=b.e)return a.e<b.e;
    return a.s<b.s;
}
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i].s>>a[i].e;
    }
    sort(a+1,a+n+1,cmp);
    ll c=a[1].e;
    for(int i=1;i<=n-1;i++){
        if(a[i+1].s>=c){
            c=a[i+1].e;
            sum++;
        }
    }
    cout<<sum<<endl;
    return 0;
}
/*
0 2
1 3
2 4
3 5
5 6
6 7
*/

双指针:

题目:子序列

cpp 复制代码
描述

给定一个长度为n的数组a,找出数组内最长且无重复元素的区间,输出其长度。

例如:
n=5
a = {1 2 2 3 5}
最长无重复元素的区间的选择下标为[3,5],即选择第三个到第五个数,其区间长度为3。

输入描述

第一行一个正整数n,代表数组大小,n<=10 5第二行n个数,代表每个a[i],a[i]<=10^6
 

输出描述

一个数,代表无重复元素的最长区间长度。

用例输入 1 

5
1 2 2 3 5
用例输出 1 

3
用例输入 2 

6
1 2 1 2 3 1 
用例输出 2 

3

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll n,a[N],l=1,r=1,q,cnt,len;
map<int,int> b;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(r=1;r<=n;r++){
        if(b[a[r]]){
            while(b[a[r]]){
                b[a[l]]=0;
                l++;
            }
        }
        len=max(len,r-l+1);
        b[a[r]]++;
    }
    cout<<len;
    return 0;
}

单调栈:

题目:Aki和摩天大楼

cpp 复制代码
### 描述
Aki所在的城市里,有 N 座摩天大楼排成一排,从左到右编号为 1,2,...,N。
第 i 座大楼的高度为 A_i。

现在Aki想在这些大楼前搭建一个广告牌矩形,要求:
- 广告牌覆盖一段连续的大楼区间 `[l, r]`(\(1 \leq l \leq r \leq N\));
- 广告牌的高度为一个正整数 `h`;
- 为了不把大楼挡住,必须满足所有 \(i \in [l, r]\),都有 \(h \leq A_i\)。

也就是说,广告牌可以看作一个宽度为 \((r - l + 1)\)、高度为 \(h\) 的矩形,完全"贴"在大楼前面,并且不会超过任何一座大楼的高度。

Aki的目标是让广告牌的面积最大,面积定义为:
\[
S = (r - l + 1) \times h
\]
请你计算最大可能的广告牌面积。

---

### 输入描述
第一行输入一个整数 \(N\)。
第二行输入 \(N\) 个整数 \(A_1, A_2, \dots, A_N\)。
- \(1 \leq N \leq 10^4\)
- \(1 \leq A_i \leq 10^5\)

---

### 输出描述
输出一个整数,表示最大广告牌面积。

---

### 用例输入 1
```
6
2 4 4 9 4 9
```

### 用例输出 1
```
20
```

---

### 提示
样例解释:
选择区间 \([2,6]\),广告牌高度取 \(h = 4\),则面积为 \((6 - 2 + 1) \times 4 = 20\)。

要不要我帮你写一个**C++实现的单调栈解法**,可以高效解决这个最大矩形面积问题?

代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
ll n,a[N],l[N],r[N],sum;
int main(){
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];//高度
    }
    stack<ll> s;
    for(int i=n;i>=1;i--){
        while(s.size() && a[s.top()]>=a[i])s.pop();
        r[i]=!s.size()?n+1:s.top();
        s.push(i);
    }
    while(s.size())s.pop();
    for(int i=1;i<=n;i++){
        while(s.size() && a[s.top()]>=a[i])s.pop();
        l[i]=!s.size()?0:s.top();
        s.push(i);
    }
    for(int i=1;i<=n;i++){
        sum=max(sum,(r[i]-l[i]-1)*a[i]);
        //cout<<l[i]<<' '<<r[i]<<endl;
    }
    cout<<sum<<endl;
    return 0;
}
相关推荐
m0_686041612 小时前
C++中的适配器模式变体
开发语言·c++·算法
AndrewHZ2 小时前
【AI黑话日日新】什么是AI智能体?
人工智能·算法·语言模型·大模型·llm·ai智能体
wWYy.2 小时前
算法:二叉树最大路径和
数据结构·算法
葱明撅腚2 小时前
利用Python挖掘城市数据
python·算法·gis·聚类
We་ct2 小时前
LeetCode 36. 有效的数独:Set实现哈希表最优解
前端·算法·leetcode·typescript·散列表
weixin_395448912 小时前
main.c_cursor_0129
前端·网络·算法
CS创新实验室2 小时前
《计算机网络》深入学:路由算法与路径选择
网络·计算机网络·算法
一条大祥脚2 小时前
ABC357 基环树dp|懒标记线段树
数据结构·算法·图论
tod1132 小时前
力扣高频 SQL 50 题阶段总结(四)
开发语言·数据库·sql·算法·leetcode