首页 > 其他分享 >[USACO22OPEN] Up Down Subsequence P

[USACO22OPEN] Up Down Subsequence P

时间:2023-11-17 16:48:08浏览次数:25  
标签:USACO22OPEN int Up Down Subsequence 转移

[USACO22OPEN] Up Down Subsequence P

注意到这个问题是不弱于直接求 LIS 的,因此考虑 dp。

设 \(f_i\) 表示以 \(i\) 结尾的最长这个什么串的长度,显然没办法直接转移,那么暴力的想法就是多设一维,这样自然就寄了。我们考虑到这样一件事情:如果我们假装对于所有的 \(j\),\(j < f_i\) 时以 \(i\) 结尾的长度为 \(j\) 的子序列都可行,这样就可以直接维护两个 BIT 转移了,但是正确性可能会有问题。

我们其实只需要求出正确的 \(f_i\),假设下一个转移的本来应该是 U,那么我们找到在 \(f_i\) 之前的第一个 \(D\),然后认为从 \(i\) 也可以转移出这个 D。那么能转移 D 出去的点按照是否比原先转移 D 的那个点小分为两部分,对于原先不能转移的部分,我们注意到其实可以从中间的点转移出更大的答案,因此对转移没有影响;而对于原先就可以转移的部分则显然是正确的。因此这个做法是对的!

const int N = 3e5 + 10;
int n, a[N];
char s[N];

struct BIT {
  int lowbit(int x) {
    return x & -x;
  }
  int tr[N];
  void add(int x, int y) {
    for(; x <= n; x += lowbit(x))
      tr[x] = max(tr[x], y);
  }
  int query(int x) {
    int res = 0;
    for(; x; x -= lowbit(x))
      res = max(res, tr[x]);
    return res;
  }
}s1, s2;
int f[N];
int pre[N][2];

int main() {
  read(n);
  for(int i = 1; i <= n; ++i)
    read(a[i]);
  scanf("%s",s + 1);
  for(int i = 1; i < n; ++i) {
    pre[i][0] = pre[i - 1][0], pre[i][1] = pre[i - 1][1];
    if(s[i] == 'U') pre[i][0] = i;
    else pre[i][1] = i;
  }
  int ans = 0;
  for(int i = 1; i <= n; ++i) {
    f[i] = max(s1.query(a[i]), s2.query(n - a[i] + 1)) + 1;
    ans = max(ans, f[i]);
    if(i < n) {
      s1.add(a[i], pre[f[i]][0]);
      s2.add(n - a[i] + 1, pre[f[i]][1]);
    }
  }
  printf("%d\n",ans - 1);
}

标签:USACO22OPEN,int,Up,Down,Subsequence,转移
From: https://www.cnblogs.com/DCH233/p/17839104.html

相关文章

  • MarkDown文件插入公式(常用格式)
    1、插入公式markdown支持插入公式,书写公式需要按照特定格式来写,涉及到希腊字母、符号、角标、基本语法等内容需要熟悉,1.1句中插入公式表达式前后插入$即可,比如$\alpha$,显示为$\alpha$1.2公式独立一行大公式或者复杂公式适合独立一行显示,表达式前后插入$$即可,写的时候也在......
  • 线段树-多个懒标记pushdown
    P3373【模板】线段树2这里需要用到两个懒标记,一个懒标记为add,记录加,另一个懒标记为mul,记录乘。我们需要规定一个优先级,然后考虑如何将懒标记下传。这里无非有两种顺序,一种是先乘后加,另一种是先加后乘。我们先看先加后乘。\[(sum+add1)*mul1\]当我们的懒标记$add2、......
  • 狂神Markdown基础操作学习记录
    Markdown学习标题一级标题:#+空格+标题二级标题:##+空格+标题三级标题:###+空格+标题四级标题:####+空格+标题以此类推(最多到六级标题)字体Hello,World!两边加上**:加粗Hello,World!两边一个*:斜体Hello,World!两边三个***:斜体加粗Hello,World!删除线:两边波浪号(注意英文输入法)......
  • Markdown使用教程
    Markdown1.介绍Markdown是一种轻量级标记语言,它允许人们使用易读易写的纯文本格式编写文档。Markdown语言在2004由约翰·格鲁伯(英语:JohnGruber)创建。Markdown编写的文档可以导出HTML、Word、图像、PDF、Epub等多种格式的文档。Markdown编写的文档后缀为.md,.mark......
  • trpora markdown笔记
    前言此为个人markdown笔记,不定时更新。正文1.mermaid使用横向流程图源码graphLRa(起始)-->b(中间)b-->c1<-->db-->c2<-->db-->c3<-->dgraphLRa(起始)-->b(中间)b-->c1<-->db-->c2<-->db-->c3<-->d参考文章:[1].如何使用Typora......
  • vcpkg downloads installed 等目录做啥用的?
    GitHubCopilot:vcpkg是一个C++包管理器,它有几个重要的目录:downloads:这个目录用于存储下载的包的源代码。当你安装一个包时,vcpkg首先会下载包的源代码到这个目录。installed:这个目录用于存储已经构建和安装的包。当你构建一个包时,vcpkg会在这个目录下创建一个新的子目录......
  • Markdown语法学习笔记
    MyFirstMarkdownFile(Markdown常用语法总结)文章标题文字前以#数量为一级、二级、三级、四级标题,例如本文标题,我使用了:#MyFirstMarkdownFile(Markdown常用语法总结)同样的,SecondTitle(##二级标题)ThirdTitle(###三级标题)FourthTitle(####四级标题)正文文字直......
  • node+express服务给前端提供markdown数据,前端渲染md文件在页面上
    本文介绍后端怎么把markdown文件发给前端,前端又怎么渲染在页面中。先看效果图md文件代码: 前端网页渲染: 先介绍node+express怎么提供接口:constexpress=require("express");constrouter=express.Router();constfs=require("fs");router.get("/api/getMark......
  • markdown语法基础
    [TOC]一、基础语法1、标题[数个#+空格前置]标题快捷键:Ctrl+1:一级标题Ctrl+2:二级标题Ctrl+3:三级标题Ctrl+4:四级标题Ctrl+5:五级标题Ctrl+6:六级标题一级标题二级标题三级标题四级标题五级标题六级标题2、加粗[用**或__包围]--快捷键:选中文字ctrl+B......
  • Markdown常用
    Markdown学习笔记标题(几级标题就是几个#号+空格,最多6级)三级标题四级标题五级标题六级标题字体helloworld(前后两个*)helloworld(前后一个*)helloworld(前后三个*)helloworld(前后两个~)引用(>+空格)再小的帆也能远航分割线(三个-或者三个*)图片格式:![图片名称]+(本地地址......