牛客每日一题
tokitsukaze and Soldier —2020.3.25
题意:
给定n个物品,每个物品有价值v_i和限制数量s_i表示选取物品的总个数不超过s_i,求最大价值
思路:
我一开始想的是dp,WA了后才意识到这样不可取
枚举选择多少件物品,显然所有不低于此限制的物品都能被选择,具体做法是:
物品按照s_i从大到小排序,然后枚举s_i,用堆保留最大的s_i件物品。时间复杂度为O(nlogn)

#include <cstdio> #include <cstring> #include <iostream> #include <queue> #include <algorithm> #define ll long long #define inf 4e18 using namespace std; const int maxn = 1e5+100; int n; priority_queue<ll, vector<ll>, greater<ll> > que; struct node{ int v, s; }a[maxn]; bool cmp(node x, node y){ return x.s > y.s; } int main(){ scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d%d", &a[i].v, &a[i].s); sort(a+1, a+1+n, cmp); ll ans = 0, sum = 0; for(int i = 1; i <= n; i++){ sum += a[i].v; que.push(a[i].v); while(que.size()>a[i].s){ sum -= que.top(); que.pop(); } ans = max(ans, sum); } printf("%lld", ans); }
合并回文子串 —2020.3.26
题意:
给定a, b两个字符串,将他们合并成字符串c,且保证c中各字符在原串中的相对位置不变,求c最长回文子串的长度
思路:
说实话拿到这题看了半天并没有思路,还是得看题解
巨佬说看到数据范围可以想到区间dp,结合这类题目要求解的答案好像的确是这样的
我们用f[l1][r1][l2][r2]来表示在s1中选取s1_{l1}到s1_{r2},在s2种选取s2_{l1}到s2_{r2}是否能构成回文串
考虑转移,由于字符串终串中字符的相对位置不能改变,所以只有这四种可能的转移:
最后需要注意的细节:
当两个字符串最多选出一个字符时,此时显然有f[l1][r1][l2][r2]=1,作为边界条件

#include <cstdio> #include <cstring> #include <algorithm> #define pb push_back using namespace std; char s1[55], s2[55]; int T, f[55][55][55][55]; int main(){ scanf("%d", &T); while(T--){ memset(f, 0, sizeof(f)); scanf("%s%s", s1+1, s2+1); int len1 = strlen(s1+1), len2 = strlen(s2+1), ans = 0; for(int i = 0; i <= len1; i++){ //s1区间长度 for(int j = 0; j <= len2; j++){ //s2区间长度 for(int l1 = 1, r1 = l1+i-1; r1 <= len1; l1++, r1++){ for(int l2 = 1, r2 = l2+j-1; r2 <= len2; l2++, r2++){ if(i+j<=1) f[l1][r1][l2][r2] = 1; //边界 else{ if(s1[l1]==s1[r1]) f[l1][r1][l2][r2] |= f[l1+1][r1-1][l2][r2]; if(s1[l1]==s2[r2]) f[l1][r1][l2][r2] |= f[l1+1][r1][l2][r2-1]; if(s2[l2]==s2[r2]) f[l1][r1][l2][r2] |= f[l1][r1][l2+1][r2-1]; if(s2[l2]==s1[r1]) f[l1][r1][l2][r2] |= f[l1][r1-1][l2+1][r2]; } if(f[l1][r1][l2][r2]) ans = max(ans, r1-l1+1+r2-l2+1); } } } } printf("%d\n", ans); } }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步