2019 牛客多校 第六场
题目链接:https://ac.nowcoder.com/acm/contest/886#question 链接
A:
题意:签到,读题读了好久......
D:
题意:给定n个物品,k个体积相等的盒子,求一个最小体积使得所有的物品都可以装到盒子里。装盒子要满足有大的就装大的,没有大的才能装小的的策略
题解:我们要求的答案不满足:若ans成立,则ans+1成立(即不符合单调性)。
对于下面这个样例
15 5
39 39 39 39 39 60 60 60 60 60 100 100 100 100 10
199 为一个合法的答案,但 200 不是,201 也不是。
这个数据量,直接暴力枚举ans,再判断是否满足即可。
multiset的相关操作:https://blog.csdn.net/hlsdbd1990/article/details/46501391
http://c.biancheng.net/view/545.html
#include <bits/stdc++.h> using namespace std; const int MAXN=1e3+5; int n, k, a[MAXN], vis[MAXN]; bool judge1(int ans) //372ms { sort(a, a+n); for(int i=0; i<n; i++) vis[i]=0; for(int i=0; i<k; i++) { int nv=ans; for(int j=n-1; j>=0; j--) { if(!vis[j] && nv>=a[j]) { nv-=a[j]; vis[j]=1; } } } for(int i=0; i<n; i++) if(!vis[i]) return false; return true; } bool judge2(int ans) //310ms { multiset<int> S; multiset<int>::iterator it; for(int i=0; i<n; i++) S.insert(a[i]); for(int i=0; i<k; i++) { int nv=ans; while(!S.empty() && (it=S.upper_bound(nv))!=S.begin()) { it--; nv-=*it; S.erase(it); } } return S.empty(); } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int T, kase=0; for(cin>>T; T--; ) { cin>>n>>k; int sum=0, mv=0; for(int i=0; i<n; i++) { cin>>a[i]; sum+=a[i]; mv=max(mv, a[i]); } for(int ans=max(mv, (int)ceil(sum/k)); ans; ans++) { if(judge2(ans)) { cout<<"Case #"<<++kase<<": "<<ans<<endl; break; } } } return 0; }
J:
题意:有i个技能,每次从j-1级升级到j级都有花费cij,然后所有技能都达到j级(至少有一个是j级,其他的可以大于等于j级)送dj块钱(cij和dj可以是负数),问你最多能赚多少。
题解:用st表维护升级花费矩阵的前缀和,枚举可以可以达到的等级,注意可以达到等级从0开始,建表的时候把0也带上, 求最优情况即可。复杂度:n*m*logm+n*m ,960ms
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=1e3+5; int n, m; ll b[MAXN], a[MAXN][MAXN], st[MAXN][MAXN][20]; void make_st() { for(int i=1; i<=n; i++) for(int j=1; j<=m+1; j++) st[i][j][0]=a[i][j]; for(int k=1; k<=n; k++) for(int j=1; (1<<j)<=m; j++) for(int i=0; i+(1<<j)-1<=m; i++) st[k][i][j]=min(st[k][i][j-1], st[k][i+(1<<j-1)][j-1]); } ll ask(int i, int l, int r) { int k=log2(r-l+1); return min(st[i][l][k], st[i][r-(1<<k)+1][k]); } int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); int T, kase=0; for(cin>>T; T--; ) { cin>>n>>m; for(int i=1; i<=n; i++) for(int j=1; j<=m; j++) { cin>>a[i][j]; a[i][j]=a[i][j]+a[i][j-1]; } for(int i=1; i<=m; i++) { cin>>b[i]; b[i]=b[i]+b[i-1]; } make_st(); ll ans=0; for(int i=0; i<=m; i++) { ll s1=0; for(int j=1; j<=n; j++) s1=s1+ask(j, i, m); for(int j=1; j<=n; j++) { ll s2=s1-ask(j, i, m)+a[j][i]; ans=max(ans, b[i]-s2); } } printf("Case #%d: %lld\n", ++kase, ans); } return 0; }