首页 > 编程语言 >C++U4-第11课-综合练习

C++U4-第11课-综合练习

时间:2023-12-31 19:44:28浏览次数:30  
标签:11 int U4 mid C++ st ++ ans include

学习目标

 贪心算法

 

[导弹拦截]

 

【算法分析】
首先考虑第一问,即序列中的最长不上升子序列。

令 g 为以 i 结尾的最长不上升子序列的值,那么可以枚举 g 
1
​
 ~ gi−1,若 a 
j
​
 ≤a 
i
​
 ,则 g 
i
​
 =max(g 
i
​
 ,g 
j+1
​
 ),否则 g 
i
​
 =max(g 
i
​
 ,g 
j
​
 )。这么做显然是 O(n 
2
 ) 的,需要进行优化。

若 a 
i
​
  小于等于 g 的最后一个元素,那么显然将 a 放至 g 的末尾。否则,将 a 
i
​
  替换掉 g 中第一个小于等于 a 
i
​
  的值。为什么这样做呢?假设 g 
j
​
  是 g 中第一个小于等于 a 
i
​
  的值,那么 g 
j−1
​
  一定大于 a 
i
​
 ,若替换掉这一个,则肯定不划算(因为 g 
j−1
​
  会变小,但是答案没有变),而替换掉 g 
j
​
 ,则答案不变的同时 g 
j
​
  会变大,更加划算。

那么答案显然就是 g 数组的长度,可以用二分来查找「g中第一个小于等于a 
i
​
  的值」,复杂度(nlog 
2
​
 n)。

第二问见注释。

【参考代码】
#include <iostream>
using namespace std;

const int N = 5e5 + 10;
int a[N], x, n, dp[N], maxn;
int g[N], cnt;

int main() {
    while (cin >> x) a[++n] = x;
    g[0] = 5e4; 
    for (int i = 1; i <= n; i++) {   //构造最长不上升子序列 
        if (a[i] <= g[cnt]) g[++cnt] = a[i]; //ai小于 g 中最后一个元素,将 ai 放末尾 
        else {  //ai大于 g 中最后一个元素,找到 g 中第一个小于等于 ai 的值元素,交换 
            int l = 1, r = cnt;
            while (l < r) {
                int mid = (l + r) >> 1;
                if (g[mid] < a[i]) r = mid;
                else l = mid + 1;
            }
            g[l] = a[i];
        }
    }
    cout << cnt << endl;   // 答案为 最长不上升子序列 的长度 
    cnt = 0;
    g[0] = -5e4;
    for (int i = 1; i <= n; i++) {   //gi表示第 i 个系统拦截的最低的导弹是什么,是一个上升子序列
        if (a[i] > g[cnt]) g[++cnt] = a[i]; //ai 大于 g 中最后一个元素,需要新的导弹拦截系统 
        else { //ai 小于等于 g 中最后一个元素, 找到 g 中第一个大于等于 ai 的元素,交换
            int l = 1, r = cnt;
            while (l < r) {
                int mid = (l + r) >> 1;
                if (g[mid] >= a[i]) r = mid;
                else l = mid + 1;
            }
            g[l] = a[i];
        }
    }
    cout << cnt << endl;   
    return 0;
}
View Code

 

递推

 

 

[路径计数]

 

 

【算法分析】
状态数组 vis 对障碍物进行标记,遇到障碍物则方案数为 0。
递推式: f[i][j] = (f[i - 1][j] + f[i][j - 1]) % 100003;

【参考代码】
#include <iostream>
using namespace std;

const int N = 1e3 + 10;
int f[N][N];
bool vis[N][N];

int main() {
    int n, m;
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int x, y;
        cin >> x >> y;
        vis[x][y] = true; //标记 
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){ 
            if(!vis[i][j] ) f[i][j] = (f[i - 1][j] + f[i][j - 1]) % 100003;
            if(i == 1 && j == 1) f[i][j] = 1;
        }
    }
    cout << f[n][n];
    return 0;
}
View Code

 

二分查找

 

 

 STL容器栈

 

 

 

练习题[GITARA]

 

 

 

【算法分析】
建六个栈,代表每一根弦上的音调。

对于每次输入,如果栈顶比它小,就进栈,否则一直弹栈直到栈顶的数小于等于它。每次弹栈或进栈都要累计答案,最后输出即可。

【参考代码】
#include <iostream>
#include <stack>
using namespace std;

stack<int> st[7]; //六根弦的音调 

int main() {
    int n, p, ans = 0;
    cin >> n >> p;
    for(int i = 1; i <= n; i++){
        int x, y;
        cin >> x >> y;
        while(!st[x].empty() && st[x].top() > y){
            ans++; //栈顶比当前的大,出栈
            st[x].pop(); 
        }
        if(!st[x].empty()){ //栈里还有数 
            if(st[x].top() == y) continue;
            ans++;
            st[x].push(y); 
        } else {  //栈空直接进栈 
            ans++;
            st[x].push(y);
        }
    }
    cout << ans; 
    return 0;
}
View Code

 

前缀和与差分数组

 文件读取(重要)

 

 

 

 

[Sumy]

 

 

【算法分析】
对一条鱼来说,它的最优策略是:从小到大地吃掉其它所有的鱼。
注意到,由这个策略,可以发现鱼的存活与否满足单调性,即,如果一条鱼能活下来,比它大的鱼一定都能活下来,如果一条鱼活不下来,比它小的一定都活不下来。

注意边界情况:如果所有鱼的大小相同,则最大的鱼也没法吃掉其它所有的鱼,因此二分需要考虑所有鱼都无法活到最后的情况。

【参考代码】
#include <iostream>
#include <algorithm>
using namespace std;

const int N = 5e5 + 10;

struct node{
    int w; //质量
    int id; //编号 
}a[N];
int n;
int vis[N];

bool cmp(node x, node y){
    return x.w < y.w;
}

bool check(int x){ // 该鱼是否可以吃完其它所以的鱼 
    long long t = a[x].w;
    for(int i = 1; i <= n; i++){
        if(i == x) continue;
        if(t <= a[i].w) return false;
        t += a[i].w;
    }
    return true;
}

int main() {
    cin >> n;
    for(int i = 1; i <= n; i++){
        cin >> a[i].w;
        a[i].id = i;
    }
    sort(a + 1,a + n + 1,cmp);
    int l = 1, r = n, ans = n + 1; //当鱼的重量全部相等时,最大的鱼也不能吃掉所有的鱼,ans = n + 1 
    while(l <= r){
        int mid = (l + r) >> 1;
        if(check(mid)) {
            ans = mid;
            r = mid - 1;
        } else {
            l = mid + 1;  
        }
    }
    for(int i = 1; i <= n; i++){
        if(i < ans) vis[a[i].id] = false;
        else vis[a[i].id] = true;
    } 
    for(int i = 1; i <= n; i++){
        if(vis[i]) cout << 'T';
        else cout << 'N';
    }
    return 0;
}
View Code

 

 

本节课作业讲解分析:

链接:https://pan.baidu.com/s/17LKht99FyUpobswJRkjlnQ?pwd=91n6
提取码:91n6

 

标签:11,int,U4,mid,C++,st,++,ans,include
From: https://www.cnblogs.com/jayxuan/p/17937914

相关文章

  • C++入门-命名空间、引用、函数重载
    引言:C++是C的一个超集,即C++继承了C语言的全部特性。C++不仅包含了C的关键字、语法和语义,还增加了一些新的特性。例如命名空间、引用、函数重载等,本片博客旨在向大家分享C++相较于C语言,增加的一些新的特性。1.命名空间namespace我们知道,在C语言中编写程序时,有时会存在标识符名与标准......
  • 【C/C++】通过下面的工作来改进String类声明(即将String1.h升级为String2.h)。 a. 对+运
    通过下面的工作来改进String类声明(即将String1.h升级为String2.h)。a.对+运算符进行重载,使之可将两个字符串合并成一个。b.提供一个Stringlow()成员函数,将字符串中所有的字母字符转换为小写(别忘了cctype系列字符函数)。c.提供String()成员函数,将字符串中所有字母字符转换成大......
  • 【环境配置】vscode配置C C++开发和调试环境
    【环境配置】vscode配置CC++开发和调试环境首先区分一些基本概念,其中部分内容可能有所出入,同时本文截至2023/12/31,更多的详细区别,请查阅官方文档MinGW,MinimalistGNUforWindows,前身为mingw32,是一个用于创建MicrosoftWindows应用程序的免费开源软件开发环境。包括GNU编译器......
  • JavaWebDay11
    文件上传简介本地存储调用image的方法transferto  文件没配置的话默认大小为1M,但多数情况下是超过1M的实际项目开发中很少会用本地存储,占内存且风险高,并且无法直接访问 解决方案:企业自己开发一个或直接用其他公司的比如阿里云华为云等修改员工查询回显:......
  • 上海 110 报警后,警察出警时间规定 All In One
    上海110报警后,警察出警时间规定AllInOne公安部《110报警服务工作规范化标准》处警人员在接到处警指令后要做到快速反应。凡危及公民人身、财产安全的重大、紧急报警、求助,在市区,必须5分钟内到达现场;在郊区,必须10分钟内到达现场。关于印发《上海市公安局关于加强新时代......
  • 111
    #include<bits/stdc++.h>usingnamespacestd;intmain(){list<int>a;intb[]={1,2,3,4};list<int>c(b,b+sizeof(b)/sizeof(int));a.insert(a.begin(),c.begin(),c.end());a.insert(a.begin(),3,1);//在容器首位添加元素......
  • 111
    #include<iostream>#include<list>#include<algorithm>usingnamespacestd;intmain(){ list<int>a; intb[]={1,2,3,4}; list<int>c(b,b+sizeof(b)/sizeof(int)); a.insert(a.begin(),c.begin(),c.end()); a.insert(a.begin(),......
  • oracle11gR2表空间使用查询
    SELECTa.tablespace_name"表空间名称",100-ROUND((NVL(b.bytes_free,0)/a.bytes_alloc)*100,2)"占用率(%)",ROUND(a.bytes_alloc/1024/1024,2)"容量(M)",ROUND(NVL(b.bytes_free,0)/1024/1024,2)"空闲(M)",ROUND((a.bytes_alloc-NVL(b.byte......
  • oracle 11g分区表相关知识
    文档课题:oracle11g分区表相关知识.数据库:oracle11.2.0.41、相关知识表分区指允许用户将一个表分成多个分区,用户可以只访问表中的特定分区.可以将不同的分区存储在不同的磁盘,提高访问性能和安全性,可以独立地备份和恢复每个分区.主要有范围分区、散列分区、列表分区、复合分区.......
  • C++ opencv检测圆
     #include<opencv2/opencv.hpp>#include<opencv2/highgui/highgui.hpp>#include<opencv2/imgproc/imgproc.hpp>#include<iostream>usingnamespacecv;usingnamespacestd;intmain(intargc,char**argv){//读取图像Matsrc......