Solution -「ZJOI 2020」「洛谷 P6631」序列
阿新 • • 發佈:2021-06-26
\(\mathcal{Description}\)
Link.
給定一個長為 \(n\) 的非負整數序列 \(\lang a_n\rang\),你可以進行如下操作:
- 取 \([l,r]\),將其中所有 \(a\) 值 \(-1\);
- 取 \([l,r]\),將其中奇數下標的 \(a\) 值 \(-1\);
- 取 \([l,r]\),將其中偶數下標的 \(a\) 值 \(-1\)。
求至少需要幾次操作使得所有 \(a\) 值變為 \(0\)。
\(n\le10^5\),資料組數 \(T\le10\)。
\(\mathcal{Solution}\)
道路鋪設永放光芒!
記集族 \(\mathcal I\)
轉對偶
\[\operatorname{maximize}~~~~z'=\sum_{u=1}^na_u(s_u-t_u)\\ \operatorname{s.t.}\begin{cases} \forall P,~\sum_{u\in P}(s_u-t_i)\le1\\ \forall u,~s_u,t_u\ge0 \end{cases} \]令 \(d_u=s_u−t_u\)
複雜度 \(\mathcal O(Tn)\)(其實帶一個 \(\ge \log n\) 的 \(24\) 倍常數 qwq)。
\(\mathcal{Code}\)
/*~Rainybunny~*/ #include <cstdio> #include <cstring> #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i ) #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i ) typedef long long LL; inline int rint() { int x = 0, f = 1, s = getchar(); for ( ; s < '0' || '9' < s; s = getchar() ) f = s == '-' ? -f : f; for ( ; '0' <= s && s <= '9'; s = getchar() ) x = x * 10 + ( s ^ '0' ); return x * f; } template<typename Tp> inline void wint( Tp x ) { if ( x < 0 ) putchar( '-' ), x = -x; if ( 9 < x ) wint( x / 10 ); putchar( x % 10 ^ '0' ); } template<typename Tp> inline void chkmax( Tp& a, const Tp& b ) { a < b && ( a = b, 0 ); } inline int imax( const int a, const int b ) { return a < b ? b : a; } const int MAXN = 1e5; const LL LINF = 1ll << 60; int n, a[MAXN + 5]; LL f[MAXN + 5][2][2][2]; int main() { for ( int T = rint(); T--; ) { n = rint(); rep ( i, 1, n ) a[i] = rint(); memset( f, 0xc0, sizeof f ); f[0][0][0][0] = 0; rep ( i, 1, n ) rep ( w, -1, 1 ) { rep ( x, 0, 1 ) rep ( y, 0, 1 ) rep ( z, 0, 1 ) { if ( w + x <= 1 && w + ( i & 1 ? y : z ) <= 1 ) { chkmax( f[i][imax( imax( w, w + x ), 0 )] [i & 1 ? imax( imax( w, w + y ), 0 ) : y] [i & 1 ? z : imax( imax( w, w + z ), 0 )], f[i - 1][x][y][z] + w * a[i] ); } } } LL ans = -LINF; rep ( x, 0, 1 ) rep ( y, 0, 1 ) rep ( z, 0, 1 ) { chkmax( ans, f[n][x][y][z] ); } wint( ans ), putchar( '\n' ); } return 0; }