[loj6039]「雅礼集训 2017 Day5」珠宝 dp+决策单调性+分治

https://loj.ac/problem/6039

 

我们设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 }
View Code

 

posted @ 2018-12-27 14:51  wls001  阅读(354)  评论(0编辑  收藏  举报