题目大意
给定
n
个物品,每个物品有代价
Data Constraint
题解
注意到
Ci
很小,可以按照
Ci
先分类,每类物品按价值从小到大排序。设
fi,j
表示做完前
i
类物品,花了
可以发现,对于当前的一个位置
fi,mid
它是由
fi−1,w
转移过来,那么
fi,1∼mid
必定是由
fi−1,1∼w
转移,
fi,mid+1∼k
必定是由
fi−1,w∼k
转移。所以分治转移即可。
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std ;
#define N 1000000 + 10
typedef long long ll ;
vector < int > a[310] ;
ll f[N] , lasf[N] , nowf[N] , Sum[N] ;
int wz[N] ;
int n , K ;
ll ans ;
bool cmp( int a , int b ) { return a > b ; }
int Read() {
int ret = 0 ;
char ch = getchar() ;
while ( ch < '0' || ch > '9' ) ch = getchar() ;
while ( ch >= '0' && ch <= '9' ) {
ret = ret * 10 + ch - '0' ;
ch = getchar() ;
}
return ret ;
}
void Solve( int l , int r , int lasl , int lasr ) {
if ( l > r ) return ;
if ( l == r ) {
nowf[l] = 0 ;
for (int i = lasl ; i <= lasr ; i ++ ) {
if ( i > l ) break ;
nowf[l] = max( nowf[l] , lasf[i] + Sum[l-i] ) ;
}
return ;
}
int mid = (l + r) >> 1 ;
int wz = 0 ;
nowf[mid] = -1 ;
for (int i = lasl ; i <= lasr ; i ++ ) {
if ( i > mid ) break ;
if ( lasf[i] + Sum[mid-i] > nowf[mid] ) {
nowf[mid] = lasf[i] + Sum[mid-i] ;
wz = i ;
}
}
Solve( l , mid - 1 , lasl , wz ) ;
Solve( mid + 1 , r , wz , lasr ) ;
}
int main() {
freopen( "jewelry.in" , "r" , stdin ) ;
freopen( "jewelry.out" , "w" , stdout ) ;
n = Read() , K = Read() ;
for (int i = 1 ; i <= n ; i ++ ) {
int c = Read() , v = Read() ;
a[c].push_back(v) ;
}
for (int i = 1 ; i <= 300 ; i ++ ) {
int Size = a[i].size() ;
if ( !Size ) continue ;
sort( a[i].begin() , a[i].end() , cmp ) ;
for (int j = 1 ; j <= K / i + 1 ; j ++ ) {
Sum[j] = Sum[j-1] ;
if ( j <= Size ) Sum[j] += a[i][j-1] ;
}
for (int j = 0 ; j < i ; j ++ ) {
wz[0] = 0 ;
int x = j ;
while ( x <= K ) {
wz[++wz[0]] = x ;
lasf[wz[0]] = f[x] ;
x += i ;
}
Solve( 1 , wz[0] , 1 , wz[0] ) ;
for (int k = 1 ; k <= wz[0] ; k ++ ) f[wz[k]] = nowf[k] ;
}
}
for (int i = 1 ; i <= K ; i ++ ) {
ans = max( ans , f[i] ) ;
printf( "%lld " , ans ) ;
}
return 0 ;
}
以上.