思路
根据贪心,从开始,该块能增加一个数就再加一个数,直到不合法为止,然后开下一块.
如果暴力做的话随随便便就能卡到,肯定过不去.
所以要用倍增,每次能加个数就加,不然
.
这样复杂度为,有点危险.我们可以只对新增的数排序,然后与当前块已有元素归并,复杂度就变成了
.
代码
#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;
} 
京公网安备 11010502036488号