首页 > 代码库 > codeforces 425C
codeforces 425C
题意:给定长度为n,m<=100000的范围在100000以内的数组a,b。
现在给定两种操作:
第一种是ai,bj相等,ai,bj之前的数全删掉,费用为e,收益为1
第二种是把剩下的全部删掉,花费为之前删除的数的个数,并且得到的之前的收益(也就是必须这一步,不然1的收益都无效)
思路:刚开始看错题意了。。以为第二种操作花费为剩下的个数。。
然后多写了一段。。。还wa了。。虽然思路差不多。。
那么题目等价与a,b数组中找到最多的不相交线段。。
但是单纯这样还是要跪。。注意到s/e<=300,那么就可以二维dp
f[i][j]表示做到a[i],有j对不相交线段的最近额b数组出现在什么位置。。
那么做法就很像不下降子序列nlogn版本的做法了。。
具体看代码吧。。
code:
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define vii vector<int>::iterator 4 #define M0(a) memset(a, 0, sizeof(a)) 5 #define repf(i, a, b) for (int i = (a); i <= (b); ++i) 6 int a[101010], b[101010], n, m, s, e; 7 int f[301]; 8 vector<int> p[101010]; 9 10 void init(){11 repf(i, 1, n) scanf("%d", &a[i]);12 repf(i, 1, m) scanf("%d", &b[i]);13 for (int i = 0; i <= 100000; ++i) p[i].clear();14 repf(i, 1, m) p[b[i]].push_back(i);15 }16 17 void solve(){18 int t = s / e;19 // cout << t << endl;20 for (int i = 0; i <= t; ++i) f[i] = m+1;21 f[0] = 0;22 int ans = 0;23 for (int i = 0; i < n; ++i){24 for (int j = t; j >= 0; --j) if (f[j] <= m){25 vii it = upper_bound(p[a[i+1]].begin(), p[a[i+1]].end(), f[j]);26 if (it != p[a[i+1]].end()) f[j+1] = min(f[j+1], *it);27 }28 for (int j = 0; j <= t; ++j) if (f[j] <= m)29 if (j * e + f[j] + i + 1 <= s) ans = max(ans, j); 30 }31 cout << ans << endl;32 }33 34 int main(){35 // freopen("a.in", "r", stdin);36 while (scanf("%d%d%d%d", &n, &m, &s, &e) != EOF){37 init();38 solve();39 }40 }
codeforces 425C
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。