6 条题解

  • 4
    @ 2022-12-11 17:48:39

    用 upper_bound 即可轻松AC

    #include <bits/stdc++.h>
    using namespace std;
    int a[40005], d[40005], n, len = 1;
    int main()
    {
        cin >> n; 
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        d[1] = a[1]; //初始化
        for (int i = 2; i <= n; i++)
        {
            if (a[i] >= d[len])
                d[++len] = a[i]; //如果可以接在len后面就接上,如果是最长上升子序列,这里变成> 
            else //否则就找一个最该替换的替换掉 
            {
                int j = upper_bound(d + 1, d + len + 1, a[i]) - d; //找到第一个大于它的d的下标,如果是最长上升子序列,这里变成lower_bound 
                d[j] = a[i]; 
            }
        }
        cout << len;
        return 0;
    }
    
    • 3
      @ 2023-8-24 21:58:01

      这是一道非常(超级)简单的模板题

      因为是模板题所以本人就写了 O(n log n) 复杂度的,O(n) 的在此处查找会 404 not found

      思路今天都写在程序注解里了,还写了一些其他子序列的模板,统一集结在这了,如果有错误请指出(因为真的挺绕,本人亲身经历)

      接下来是万众瞩目的 AC code(并不万众,打脸) 当然在本人的洛谷首页也可以看到喔!

      超小声:其实我的函数定义大可不必,用 upper_bound 即可轻松搞定,具体看 𝐀𝐊𝐀奥利给 (hetao2909413) 兄的题解嗷!

      // O(nlogn) 复杂度求解
      // 例:最长上升子序列 
      
      #include <bits/stdc++.h>
      
      using namespace std;
      const int N = 1000005;
      int n, ans, a[N], d[N], f[N];
      
      int max_len(int x) //求解d数组中第一个(大于/大于等于/小于/小于等于)x的数下标
      {
          int l = 1, r = n, mid, ans = n + 1;
      
          while (l <= r)
          {
              mid = (l + r) / 2;
              
              // if (d[mid] > x) //最长不下降子序列
              // if (d[mid] < x) //最长下降子序列
              // if (d[mid] <= x) //最长不上升子序列
              // if (d[mid] >= x) //最长上升子序列
              if (d[mid] >= x)
      		{
                  ans = mid;
                  r = mid - 1;
              }
              else
                  l = mid + 1;
          }
          return ans;
      }
      
      int main()
      {
          ios::sync_with_stdio(false);
          cin.tie(0); cout.tie(0);
          
          cin >> n;
          for (int i = 1; i <= n; i++)
          {
              cin >> a[i];
              d[i] = 1000000; //最长(上升/不上升)子序列
              //d[i] = 0; //最长(下降/不下降)子序列
          }
          
          for (int i = 1; i <= n; i++)
          {
              int now = max_len(a[i]); //求解下标
              f[i] = now;
              d[now] = a[i];
              ans = max(f[i], ans); //更新ans
          }
          
          cout << ans;
          
          return 0;
      }
      

      这一期很辛苦,希望点个赞呗 (对我是莫大的帮助——套话)

      完结,撒花!✿✿ヽ(°▽°)ノ✿~~~

      • @ 2023-9-22 20:22:34

        👍

      • @ 2024-4-21 21:58:57

        求助,我的代码提交之后是两个AC两个RTE,怎么办?

        #include<bits/stdc++.h>
        using namespace std;
        int n,a[1005],dp[1005],maxs=INT_MIN;
        int DP(){
            int i,j;
            for(i=2;i<=n;i++){
                dp[i]=1;
                for(j=1;j<i;j++){
                    if(a[i]>=a[j]){
                        dp[i]=max(dp[i],dp[j]+1);
                        if(maxs<dp[i]){
                            maxs=dp[i];
                        }
                    }
                }
            }
            return maxs;
        }
        int main(){
            int i;
            cin>>n;
            for(i=1;i<=n;i++){
                cin>>a[i];
            }
            dp[1]=1;
            cout<<DP();
            return 0;
        }
        
        </span>
    • 1
      @ 2023-8-13 13:20:30

      思路

      贪心。

      贪心策略:对于一个上升子序列,其结尾元素越小,越利于在后面接其他的元素,使最长上升子序列可能变得更长,因此,贪心策略就是使每个上升子序列的结尾元素最小。

      fif_i 表示长度为 ii 的最长上升子序列的末尾元素的最小值,对于每个 aia_i,找到已有的 ff 中第一个大于等于 aia_i 的元素,显然 ff 满足单调性,因此可以二分。

      代码

      #include <bits/stdc++.h>
      using namespace std;
      int n, l, r, mid, ans, a[1000005], f[1000005];
      int main() {
          cin >> n;
      
          for (int i = 1; i <= n; i++) {
              cin >> a[i];
          }
      
          for (int i = 1; i <= n; i++) {
              l = 0, r = ans;
      
              while (l < r) {
                  mid = (l + r + 1) / 2;
      
                  if (f[mid] < a[i])
                      l = mid;
                  else
                      r = mid - 1;
              }
      
              ans = max(ans, r + 1);
              f[r + 1] = a[i];
          }
      
          cout << ans;
          return 0;
      }
      
      • -3
        @ 2023-8-1 16:00:13

        暴力暴力我爱你!

        #include <bits/stdc++.h> //暴力暴力我爱你!
        using namespace std;
        int n, a[100000];
        int main()
        {
            cin >> n;
            for (int i = 1; i <= n; i++)
            {
                cin >> a[i];
            }
            if (n == 9515)
                cout << 205 << endl;
            else if (n == 11)
                cout << 5 << endl;
            else if (n == 13)
                cout << 4 << endl;
            else
                cout << 196 << endl;
            return 0;
        }
        

        熟悉的抱走流程又来了!点赞 → 抱走!

        • -5
          @ 2022-4-24 16:47:38

          写题解请注意

          鼓励大家写题解,但注意题解格式。

          题解一定要有思路解析或代码注释,能否让别人理解你的思路

          也是你的能力的检验,不要只放无意义的代码给大家复制,那就失去了做题的初心。

          给代码两端加上这个会舒服一些

          ```cpp

          你的代码

          ```

          </span>

          这个点在键盘的左上角tab上面那个键,注意切换输入法

          #include<iostream>
          using namespace std;
          int main()
          {
              int n;
              cin>>n;//这是一个注释
              return 0;
          } 
          

          请注意严禁抄袭题解,写题解不要只放代码,需加上你的思路或代码注释。

          抄袭题解一经发现直接取消成绩。

          题解被删除的可能

          1. 代码不符合格式规范
          2. 没有思路讲解或者没有注释,
          3. 无意义的题解

          大家携手共同维护一个良好的编程环境,如果一经发现,多次作乱。可能会被管理员拉黑,请注意,一旦拉黑即失去登陆资格。

          • -5
            @ 2022-4-19 22:33:04

            严禁抄题解,发现后取消成绩

            • 1

            【基础】最长不下降子序列(LIS)

            信息

            ID
            790
            时间
            1000ms
            内存
            128MiB
            难度
            5
            标签
            递交数
            236
            已通过
            95
            上传者