题意翻译

给定一个序列 A,你可以翻转其中的一个区间内的数,求翻转后的序列的最长不下降子序列的长度。(∣A∣≤2000,1≤ai≤2|A|\le 2000,1\le a_i \le 2∣A∣≤2000,1≤ai​≤2 )

感谢@touristWang 提供的翻译

题目描述

A dragon symbolizes wisdom, power and wealth. On Lunar New Year's Day, people model a dragon with bamboo strips and clothes, raise them with rods, and hold the rods high and low to resemble a flying dragon.

A performer holding the rod low is represented by a 1 1 1 , while one holding it high is represented by a 2 2 2 . Thus, the line of performers can be represented by a sequence a1,a2,...,an a_{1},a_{2},...,a_{n} a1​,a2​,...,an​ .

Little Tommy is among them. He would like to choose an interval [l,r] [l,r] [l,r] ( 1<=l<=r<=n 1<=l<=r<=n 1<=l<=r<=n ), then reverse al,al+1,...,ar a_{l},a_{l+1},...,a_{r} al​,al+1​,...,ar​ so that the length of the longest non-decreasing subsequence of the new sequence is maximum.

A non-decreasing subsequence is a sequence of indices p1,p2,...,pk p_{1},p_{2},...,p_{k} p1​,p2​,...,pk​ , such that p1<p2<...<pk p_{1}<p_{2}<...<p_{k} p1​<p2​<...<pk​ and ap1<=ap2<=...<=apk a_{p1}<=a_{p2}<=...<=a_{pk} ap1​<=ap2​<=...<=apk​ . The length of the subsequence is k k k .

输入输出格式

输入格式:

The first line contains an integer n n n (1<=n<=2000) (1<=n<=2000) (1<=n<=2000) , denoting the length of the original sequence.

The second line contains n n n space-separated integers, describing the original sequence a1,a2,...,an a_{1},a_{2},...,a_{n} a1​,a2​,...,an​ (1<=ai<=2,i=1,2,...,n) (1<=a_{i}<=2,i=1,2,...,n) (1<=ai​<=2,i=1,2,...,n) .

输出格式:

Print a single integer, which means the maximum possible length of the longest non-decreasing subsequence of the new sequence.

输入输出样例

输入样例#1:

4
1 2 1 2
输出样例#1:

4
输入样例#2:

10
1 1 2 2 2 1 1 2 2 1
输出样例#2:

9

说明

In the first example, after reversing [2,3], the array will become [1,1,2,2]  , where the length of the longest non-decreasing subsequence is 4 .

In the second example, after reversing [3,7] , the array will become [1,1,1,1,2,2,2,2,2,1] , where the length of the longest non-decreasing subsequence is  9 .

Solution:

  本题思维题。

  因为$a_i$只有$1,2$两种可能,于是我们可以确定的是答案一定是:$[1,1,1,…]\;[2,2,2…]\;[1,1,1…]\;[2,2,2…]$这样的四段子序列(每一段都允许为空),使得第二、三段所在区间翻转得到答案(不翻转可以理解为二、三段为空序列)。

  解法一:

    我们可以从左往右做前缀和$ct1[i]$表示$[1,i]$出现的$1$的个数,同理做出后缀和$ct2[i]$表示$[i,n]$出现的$2$的个数。然后我们枚举断点$k,k\in[1,n+1]$(即二、三段的分界点),设一、二段的分界点为$p,p\in[1,k]$,三、四段的分界点为$q,q\in[k,n+1]$,那么显然答案为$(ct1[p-1])+(ct2[p]-ct2[k])+(ct1[q-1]-ct1[k])+(ct2[q])$,式子中括号括起来的为一段,这个式子可以化为$(ct1[p-1]+ct2[p]+ct1[q-1]+ct2[q])-(ct1[k]+ct2[k]),p\in[1,k],q\in[k,n+1]$,注意到对于一个确定的$k$,我们要最大化前面括号的式子,而前者可以用线段树维护下$ct1[i-1]+ct2[i]$,那么只用枚举$k$,再两次区间最大值查询,更新答案就好了。

    时间复杂度$O(n\log n)$。

  代码:

/*Code by 520 -- 10.20*/
#include<bits/stdc++.h>
#define il inline
#define ll long long
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(RE int (i)=(b);(i)>=(a);(i)--)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N=;
int n,ans,ct1[N],ct2[N],a[N],ppx[N];
struct SGT{
int maxn[N<<];
il void pushup(int rt){maxn[rt]=max(maxn[rt<<],maxn[rt<<|]);}
void build(int l,int r,int rt){
if(l==r) {maxn[rt]=ppx[l];return;}
int m=l+r>>;
build(lson),build(rson);
pushup(rt);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r) return maxn[rt];
int m=l+r>>,res=;
if(L<=m) res=max(res,query(L,R,lson));
if(R>m) res=max(res,query(L,R,rson));
return res;
}
}T; int main(){
scanf("%d",&n); int t1,t2;
For(i,,n) scanf("%d",a+i),ct1[i]=ct1[i-]+(a[i]==);
Bor(i,,n) ct2[i]=ct2[i+]+(a[i]==);
For(i,,n+) ppx[i]=ct1[i-]+ct2[i];
T.build(,n+,);
For(k,,n+) {
t1=T.query(,k,,n+,),t2=T.query(k,n+,,n+,);
ans=max(ans,t1+t2-ct1[k-]-ct2[k]);
}
cout<<ans;
return ;
}

  解法二:

    我们显然(事实上考试只想出了解法一)可以用DP来维护每段的最大值。

    定义状态$f[i][1]$表示前$i$个数中前一段的答案,$f[i][2]$表示前$i$个数中前两段的答案,$f[i][3]$表示前$i$个数中前三段的答案,$f[i][4]$表示前$i$个数中前四段的答案。

    那么不难得到状态转移方程:

    $f[i][1]=f[i-1][1]+(a_i==1)$

    $f[i][2]=max(f[i-1][1],f[i-1][2]+(a_i==2))$

    $f[i][3]=max(f[i-1][2],f[i-1][3]+(a_i==1))$

    $f[i][4]=max(f[i-1][3],f[i-1][4]+(a_i==2))$

    显然第一维是可以压掉的,时间复杂度$O(n)$。

  代码:

  

/*Code by 520 -- 10.20*/
#include<bits/stdc++.h>
#define RE register
#define For(i,a,b) for(RE int (i)=(a);(i)<=(b);(i)++)
using namespace std;
int n,x,f[]; int main(){
scanf("%d",&n);
For(i,,n)
scanf("%d",&x),
f[]+=(x==),
f[]=max(f[],f[]+(x==)),
f[]=max(f[],f[]+(x==)),
f[]=max(f[],f[]+(x==));
cout<<f[];
return ;
}
 
 
 
 
 
 
 
 
 
 
 
 

CF933A A Twisty Movement的更多相关文章

  1. Codeforces 934C - A Twisty Movement

    934C - A Twisty Movement 思路:dp 很容易想到要预处理出1的前缀和pre[i]和2的后缀和suf[i] 然后枚举区间,对于每个区间如果能求出最长递减序列的长度,那么就能更新答 ...

  2. Codeforces 934.C A Twisty Movement

    C. A Twisty Movement time limit per test 1 second memory limit per test 256 megabytes input standard ...

  3. Codeforces Round #462 (Div. 2) C. A Twisty Movement

    C. A Twisty Movement time limit per test1 second memory limit per test256 megabytes Problem Descript ...

  4. CF933A/934C A Twisty Movement

    思路: 实际上是求原序列中最长的形如1......2......1......2......的子序列的长度.令dp[i][j](1 <= j <= 4)表示在子序列a[1]至a[i]中形如 ...

  5. [Codeforces 933A]A Twisty Movement

    Description 题库链接 给你一个长度为 \(n\) 的只含有 \(1,2\) 的序列.你可以选择其中的一段 \([l,r]\) ,将区间翻转,翻转后使得单调不下降序列最长.求最长长度. \( ...

  6. cf934C. A Twisty Movement(思维题)

    题意 题目链接 Sol 这题最直接的维护区间以0/1结尾的LIS的方法就不说了. 其实我们可以直接考虑翻转以某个位置为中点的区间的最大值 不难发现前缀和后缀产生的贡献都是独立的,可以直接算.维护一下前 ...

  7. E - A Twisty Movement

    A dragon symbolizes wisdom, power and wealth. On Lunar New Year's Day, people model a dragon with ba ...

  8. Codeforces Round #462 (Div. 2), problem: (C) A Twisty Movement (求可以转一次区间的不递增子序列元素只有1,2)

    题目意思: 给长度为n(n<=2000)的数字串,数字只能为1或者2,可以将其中一段区间[l,r]翻转,求翻转后的最长非递减子序列长度. 题解:求出1的前缀和,2的后缀和,以及区间[i,j]的最 ...

  9. 【Codeforces 933A】A Twisty Movement

    [链接] 我是链接,点我呀:) [题意] [题解] 因为只有1和2. 所以最后肯定是若干个1接着若干个2的情况. 即11...11222...222这样的. 1.首先考虑没有翻转的情况. 那么就直接枚 ...

随机推荐

  1. HDU 4857 逃生(反向建边的拓扑排序+贪心思想)

    逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  2. Kubernetes哪一点最打动你?或者,它发布过的哪一项特性让你认为最厉害?

    kubernates 打动我的地方应该是他解决了docker 的一个痛点,各个docker之间的通信以及集成管理.因为这跟微服务很像,微服务之间也是需要通信和统一管理.知识总是相同的,在这里就体现出来 ...

  3. 【转】PHP之FastCGI与mod_php详解

    原文地址:http://article.gitos.cn/2015/Aurthur/PHP-Mod-PHP-And-Fast-CGI-Explain.html 背景 PHP最常用的方式是以模块的方式( ...

  4. 非const引用不能指向临时变量

    没找到具体原因,MSDN看到下面这句,VC是从2008才有这一限制的,感觉就是从语法上对临时变量增加了限定,因为一般说来修改一个临时变量是毫无意义的,通过增加限定,强调临时变量只读语义.虽然实际上修改 ...

  5. Java面试题,Java三大特性之一——多态的理解

    首先我们知道Java是一门面向对象的语言 面向对象三大特性,封装.继承.多态. 封装.继承.多态 ↓ 无论是学习路线,还是众人的口语习惯,都是按照这个这样进行排序,这是有原因的.因为封装好了才能继承, ...

  6. python with原理

    在python2.5+中可以用with来保证关闭打开的文件 with open('hello.txt') as f: do some file operations 为什么要引入with呢? 在之前如 ...

  7. 2017-2018-2 20155204《网络对抗技术》EXP5 MSF基础应用

    一.基础问题回答 用自己的话解释什么是exploit,payload,encode exploit:利用靶机系统中的一些漏洞进行攻击的过程,除去前期准备的工作,这一步是实施攻击. payload:载荷 ...

  8. WPF样式(Style)入门

    原文:WPF样式(Style)入门 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_34802416/article/details/78231 ...

  9. Luogu P1993 小 K 的农场

    其实很早以前就打好了,但一直忘记写了. 也就是差分约束的模板题. 关于差分约束,也就是用来求关于一些不等式互相约束算出最优解. 推荐一个讲的很好的博客:http://www.cppblog.com/m ...

  10. 在sourceinsight中添加快速注释 Ctrl+/

    1.搜索文件:utils.em(C:\Program Files (x86)\Source Insight 3)2.用sourceinsight打开文件:utils.em3.在文件末尾添加下面代码 m ...