想了个思路不敢交,发现 luogu 没有我的题解的思路,就麻利码出来交了,开水,逃
假如完全非降,直接随便删就行
a n s = ∑ i = 1 n ( n − i + 1 ) ans=\sum_{i=1}^{n}(n-i+1) ans=i=1∑n(n−i+1)
考虑只有一个下降的地方,答案并不改变
考虑有一个沟
n u m [ l ] < = n u m [ r ] a n d n u m [ l ] > max l < i < r ( n u m [ i ] ) num[l]<=num[r]\ and\ num[l]>\max_{l<i<r}(num[i]) num[l]<=num[r] and num[l]>l<i<rmax(num[i])
我们发现要维护这序列的单调性,只需要关注两个区间就行,
[ min l < i < r ( n u m [ i ] ) , max l < i < r ( n u m [ i ] ) ] [\min_{l<i<r}(num[i]),\max_{l<i<r}(num[i])] [l<i<rmin(num[i]),l<i<rmax(num[i])]
和
[ l < i < r ( i f ( n u m [ i − 1 ] > n u m [ i ] ) ) ( min 1 < j < i ( n u m [ j ] ) a n d n u m [ j ] > n u m [ i ] ) , n u m [ l ] ] [_{l<i<r}(if(num[i-1]>num[i]))(\min_{1<j<i}(num[j])\ and \ num[j]>num[i]),num[l]] [l<i<r(if(num[i−1]>num[i]))(1<j<imin(num[j]) and num[j]>num[i]),num[l]]
我们至少要删掉其中一个区间,因为只要包含这两个区间就行,我们可以在计算答案时枚举左端点,第二个区间我们命名为 [ l 1 , r 1 ] [l1,r1] [l1,r1],第一个是 [ l 2 , r 2 ] [l2,r2] [l2,r2],可以发现 l 1 < l 2 l1<l2 l1<l2的,细分为 3 3 3个区间, [ 1 , l 1 ] [1,l1] [1,l1]、 [ l 1 + 1 , l 2 ] [l1+1,l2] [l1+1,l2]、 [ l 2 + 1 , x ] [l2+1,x] [l2+1,x]左端点在第一个区间的,删除区间的右端点至少是r1,同理其它区间的左端点删除区间分别是 r 2 r2 r2、无解(因为一定不能删掉其中一个区间,我们用一个值 i n f inf inf表示它),区间修改当然是线段树辣,来个懒标暴力线段树
当考虑多个沟时,每个沟都得删除至少一个区间,注意到对应每一个左端点,它要删除的最小区间的右端点不能在经过一个沟之后变小,取个 max \max max就行,我们用线段树的懒标也是取个 max \max max
ac 代码
# include <bits/stdc++.h>
using namespace std ;
using ll = long long ;
namespace predefine {
const long long inf = 0x3f3f3f3f3f3f3f3f ;
using ll = long long ;
# define IOS iostream::sync_with_stdio ( 0 ) ; cin.tie ( 0 ) ;
# define af( i , a , b ) for ( ll i = a ; i <= b ; ++ i )
# define df( i , a , b ) for ( ll i = a ; i >= b ; -- i )
}
using namespace predefine ;
template <typename T>
class SegtreeLazyRangeSet {
vector<T> tree , lazy ;
vector<T> *arr ;
ll n , root , n4 , end ;
void maintain ( ll cl , ll cr , ll p ){
ll cm = cl + ( ( cr - cl ) >> 1 ) ;
if ( cl != cr && lazy [ p ] ) {
lazy [ p << 1 ] = max ( lazy [ p << 1 ] , lazy [ p ] ) ;
lazy [ p << 1 | 1 ] = max ( lazy [ p << 1 | 1 ] , lazy [ p ] ) ;
}
}
void set_all ( ll l , ll r , ll p ) {
if ( l == r ) {
( *arr ) [ l ] = max ( ( *arr ) [ l ] , (ll) lazy [ p ] ) ;\
return ;
}
maintain ( l , r , p ) ;
ll m = ( l + r ) >> 1 ;
set_all ( l , m , p << 1 ) ; set_all ( m + 1 , r , p << 1 | 1 ) ;
}
void range_set ( ll l , ll r , T val , ll cl , ll cr , ll p ) {
if ( l <= cl && r >= cr ) {
lazy [ p ] = max ( lazy [ p ] , val ) ;
return ;
}
ll m = cl + ( ( cr - cl ) >> 1 ) ;
maintain ( cl , cr , p ) ;
if ( l <= m ) range_set ( l , r , val , cl , m , p << 1 ) ;
if ( r > m ) range_set ( l , r , val , m + 1 , cr , p << 1 | 1 ) ;
}
public :
explicit SegtreeLazyRangeSet < T > ( vector < T >& v ) {
n = v.size () ;
n4 = n * 4 ;
lazy = vector < T > ( n4 , 0 ) ;
arr = &v ;
end = n - 1 ;
root = 1 ;
}
void show ( ll p , ll depth = 0 ) {
if ( p > n4 || tree [ p ] == 0 ) return ;
show ( p << 1 , depth + 1 ) ;
for ( ll i = 0 ; i < depth ; ++ i ) putchar ( '\t' ) ;
printf ( "%d:%d\n", tree [ p ] , lazy [ p ] ) ;
show ( p << 1 | 1 , depth + 1 ) ;
}
T range_sum ( ll l , ll r ) { return range_sum ( l , r , 0 , end , root ) ; }
void range_set ( ll l , ll r , ll val ) { if ( l <= r ) range_set ( l , r , val , 0 , end , root ) ; }
void set_all () { set_all ( 0ll , end , root ) ; }
};
void solve ()
{
ll n , x ; cin >> n >> x ;
vector < ll > v ( n ) ;
af ( i , 0 ,n - 1 ) cin >> v [ i ] , -- v [ i ] ;
vector < ll > ans ( x ) ;
iota ( ans.begin () , ans.end () , 0 ) ;
SegtreeLazyRangeSet < ll > tree ( ans ) ;
set < ll > s ; s.emplace ( v [ 0 ] ) ;
af ( i , 1 , n - 1 ) {
s.emplace ( v [ i ] ) ;
if ( v [ i ] < v [ i - 1 ] ) {
ll l1 = v [ i ] , r1 = v [ i ] , l2 = * ( s.upper_bound ( v [ i ] ) ) , r2 = *( s.rbegin () ) ;
++ i ;
while ( i <= n - 1 && v [ i ] < r2 ) {
l1 = min ( l1 , v [ i ] ) ;
r1 = max ( r1 , v [ i ] ) ;
s.emplace ( v [ i ] ) ;
if ( v [ i ] < v [ i - 1 ] ) {
auto tmp = s.upper_bound ( v [ i ] ) ;
l2 = min ( *tmp , l2 ) ;
}
++ i ;
}
s.emplace ( v [ i ] ) ;
tree.range_set ( 0 , l1 , r1 ) ;
tree.range_set ( l1 + 1 , l2 , r2 ) ;
tree.range_set ( l2 + 1 , x - 1 , inf ) ;
}
}
tree.set_all () ;
ll ys = 0 ;
af ( i , 0 , x - 1 ) {
if ( ans [ i ] != inf ) {
ys += ( x - 1 - ans [ i ] + 1 ) ;
}
}
cout << ys << endl ;
}
int main () {
// IOS
ll _ = 1 ;
// cin >> _ ;
while ( _ -- ) {
solve () ;
}
return 0 ;
}