[loj6039]「雅礼集训 2017 Day5」珠宝 dp+决策单调性+分治
我们设dp[i][j]表示考虑所有价值小于等于i的物品,带了j块钱的最大吸引力。
对于ci相同的物品,我们一定是从大到小选k个物品,又发现最大的k个的价值在k变大的时候增长率是单调减的。
同时对于同样的ci,被转移和转移到的状态mod ci同余。
这些dp值也具有单调性,因此这个dp具有决策单调性。
我们用分治优化转移。负责度O(c*k*logk)
1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 #include<vector> 8 #define maxn 305 9 #define maxk 50005 10 #define ll long long 11 using namespace std; 12 inline int read() { 13 int x=0,f=1;char ch=getchar(); 14 for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; 15 for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; 16 return x*f; 17 } 18 ll n,k,sz[maxn],pre=0,now=1; 19 ll dp[2][maxk],g[2][maxk]; 20 vector<ll> q[maxn]; 21 bool cmp(ll a,ll b) {return a>b;} 22 void solve(int l,int r,int ql,int qr,int x,int SZ) { 23 if(l>r||ql>qr) return; 24 int mid=ql+qr>>1,minmid=-1;ll val=0; 25 for(int i=max(l,mid-SZ);i<mid&&i<=r;i++) { 26 if(minmid==-1||g[0][i]+q[x][mid-i-1]>val) { 27 val=g[0][i]+q[x][mid-i-1];minmid=i; 28 } 29 } 30 g[1][mid]=val; 31 // if(minmid==-1) minmid=l; 32 solve(l,minmid,ql,mid-1,x,SZ);solve(minmid,r,mid+1,qr,x,SZ); 33 } 34 int main() { 35 n=read(),k=read(); 36 for(int i=1;i<=n;i++) { 37 int x=read(),y=read(); 38 q[x].push_back(y);sz[x]++; 39 } 40 for(int i=1;i<=300;i++) { 41 if(!sz[i]) continue; 42 sort(q[i].begin(),q[i].end(),cmp); 43 for(int j=1;j<sz[i];j++) q[i][j]+=q[i][j-1]; 44 for(int j=0;j<i;j++) { 45 int p=j,bk=0; 46 for(;p<=k;p+=i,bk++) g[0][bk]=dp[pre][p]; 47 solve(0,bk-1,0,bk-1,i,sz[i]); 48 p=j,bk=0; 49 for(;p<=k;p+=i,bk++) dp[now][p]=max(g[0][bk],g[1][bk]); 50 } 51 swap(now,pre); 52 } 53 for(int i=1;i<=k;i++) printf("%lld ",dp[pre][i]); 54 }
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~