思路
根据贪心,从开始,该块能增加一个数就再加一个数,直到不合法为止,然后开下一块.
如果暴力做的话随随便便就能卡到,肯定过不去.
所以要用倍增,每次能加个数就加,不然
.
这样复杂度为,有点危险.我们可以只对新增的数排序,然后与当前块已有元素归并,复杂度就变成了
.
代码
#include<bits/stdc++.h> using namespace std; #define i64 long long #pragma GCC optimize("Ofast") #define fp( i, b, e ) for ( int i(b), I(e); i <= I; ++i ) #define fd( i, b, e ) for ( int i(b), I(e); i >= I; --i ) #define go( i, b ) for ( int i(b), v(to[i]); i; v = to[i = nxt[i]] ) template<typename T> inline void cmax( T &x, T y ){ x < y ? x = y : x; } template<typename T> inline void cmin( T &x, T y ){ y < x ? x = y : x; } #define getchar() ( p1 == p2 && ( p1 = bf, p2 = bf + fread( bf, 1, 1 << 21, stdin ), p1 == p2 ) ? EOF : *p1++ ) char bf[1 << 21], *p1(bf), *p2(bf); template<typename T> inline void read( T &x ){ char t(getchar()), flg(0); x = 0; for ( ; !isdigit(t); t = getchar() ) flg = t == '-'; for ( ; isdigit(t); t = getchar() ) x = x * 10 + ( t & 15 ); flg ? x = -x : x; } const int MAXN = 5e5 + 5; int K, N, M; i64 T; int a[MAXN], b[MAXN], c[MAXN], d[MAXN]; bool check( int l, int m, int r ){ if ( r > N ) return 0; fp( i, l, m ) c[i] = b[i]; fp( i, m + 1, r ) c[i] = a[i]; sort( c + m + 1, c + r + 1 ); int i(l), j(m+1), k(l); while( i <= m && j <= r ) d[k++] = c[i] < c[j] ? c[i++] : c[j++]; while( i <= m ) d[k++] = c[i++]; while( j <= r ) d[k++] = c[j++]; i64 s(0); int t(M); i = l, j = r; while( s <= T && i < j && t-- ) s += 1ll * (d[j] - d[i]) * (d[j] - d[i]), ++i, --j; if ( s <= T ) fp( i, l, r ) b[i] = d[i]; return s <= T; } signed main(){ read(K); while( K-- ){ read(N), read(M), read(T); fp( i, 1, N ) read(a[i]); int x(1), y(1), ans(0), len(1); b[1] = a[1]; while( x < N ){ if ( !len ) ++ans, len = 1, x = ++y, b[x] = a[x]; else if ( check(x, y, y + len) ) y += len, len <<= 1; else len >>= 1; } printf( "%d\n", ans + ( x == N ) ); } return 0; }