题目
最窄的题目描述。。。
思路&题解
自己的思路
这是不可能有的
正解
首先需要发现一个性质,如果现在已经求出k的答案,那么k+2的答案序列就一定是在k的答案序列中插入两个(可以是末尾与开头) 数所得到,至于为什么,其实我也不知道,那么考虑k+2的转换,考虑CDQ
假设对于k,在区间l-mid选了k1个点,mid+1-r选了k2个点
那么对于k+2,就有一下情况:
1.在区间l-mid选k1+1个点,mid+1-r选k2+1个点
2.在区间l-mid选k1个点,mid+1-r选k2+2个点
3.在区间l-mid选k1+2个点,mid+1-r选k2个点
但是由于它是加减加减的,所以还要维护最大值和最小值
总结
CDQ分治是解决用一个子问题来计算对另一个子问题的贡献的算法,所以这道题可以刚好使用,因此dp也可以用此来优化
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e5 + 3;
int n , a[MAXN] , f[MAXN][23][2];
int w[MAXN][2];
void cdq( int l , int r , int step ){
if( l == r ) {
f[l][step][0] = a[l] , f[l][step][1] = a[l];
return ;
}
int mid = ( l + r )>> 1;
cdq( l , mid , step + 1 );
cdq( mid + 1 , r , step + 1 );
for( int i = l ; i <= r ; i ++ )
f[i][step][1] = 0x3f3f3f3f , f[i][step][0] = -0x3f3f3f3f;
int k1 = 0 , k2 = 0;
if( f[l][step+1][0] > f[mid+1][step+1][0] ) f[l][step][0] = f[l][step+1][0] , k1 = 1;
else f[l][step][0] = f[mid+1][step+1][0] , k2 = 1;
for( int i = l + 2 ; i <= r ; i += 2 ){
int k11 , k22 , tmp ;
if( l + k1 <= mid && mid + k2 + 1 <