Codeforces Round #775 - F. Serious Business
F. Serious Business
prob. :有3×n3\times n3×n个格子,每个格子有一个权值,你要从左上走到右下,每一步只能往右或往下走,刚开始的时候第二行是封锁的状态,你有一些可选的操作去解锁第二行从[Li,Ri][L_i, R_i][Li,Ri]的格子,每种操作的代价分别是kik_iki, 问最大能获得的值是多少
ideas :非常巧妙将三行的权值拆成两个函数
pref表示每行的前缀和
s[i]=pref[0][i+1]−pref[1][i]s[i] = pref[0][i +1] - pref[1][i]s[i]=pref[0][i+1]−pref[1][i]
f[i]=pref[1][i+1]−pref[2][i]+pref[2][n]f[i] = pref[1][i + 1] - pref[2][i] + pref[2][n]f[i]=pref[1][i+1]−pref[2][i]+pref[2][n]
最终的答案变成max0≤i<j<ns[i]+f[j]−cost(i,j)max_{0\le i < j < n} s[i] + f[j] -cost(i, j)max0≤i<j<ns[i]+f[j]−cost(i,j), cost指第二行解锁区间[i,j][i, j][i,j]的最小价值
// 在下面具体代码实现的时候s和f的+1-1可能和上述有些不同
直接用s+f更新答案是只解锁一个区间时候的答案,dp记录的是多个区间时候的答案(这里为了少转移只对每个操作的r端点更新值
dp是s-cost,对于每个操作Li,RiL_i, R_iLi,Ri,用s和dp更新dp[R]dp[R]dp[R], 对应的s是[L,R][L, R][L,R]区间的因为他还在第0行没有走下来,dp已经在第1行了,所以是由[L−1,R−1][L-1, R-1][L−1,R−1]转移的,(R这里不用算进去但可能算进去也没啥区别,因为-k之后肯定比本身小)
注意更新dp的时候要对区间排序
写死我了,我好菜啊,谢谢npy帮我debug,“有些人被迫参与全程”
#include <bits/stdc++.h>using namespace std;typedef long long ll;
const ll N = 5e5 + 50;
const ll inf = 0x3f3f3f3f3f3f3f3f;struct node {ll l, r;ll s, f, sf;
};node tr[N << 2];ll s[N], f[N], dp[N];void pushup(ll u) {tr[u].s = max(tr[u << 1].s, tr[u << 1 | 1].s);tr[u].f = max(tr[u << 1].f, tr[u << 1 | 1].f);tr[u].sf = max(max(tr[u << 1].sf, tr[u << 1 | 1].sf), tr[u << 1].s + tr[u << 1 | 1].f);
}void build(ll u, ll l, ll r) {if (l == r) {tr[u] = {l, r, s[l], f[l], s[l] + f[l]};} else {tr[u] = {l, r, -inf, -inf, -inf};ll mid = (l + r) >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);pushup(u);}
}void modify(ll u, ll l, ll r, ll s) {if (tr[u].l >= l && tr[u].r <= r) {tr[u].s = max(tr[u].s, s);tr[u].sf = tr[u].s + tr[u].f;return;}ll mid = (tr[u].l + tr[u].r) >> 1;if (l <= mid) modify(u << 1, l, r, s);if (r > mid) modify(u << 1 | 1, l, r, s);pushup(u);
}struct note {ll sf, s, f;
};note querySF(ll u, ll l, ll r) {if (tr[u].l >= l && tr[u].r <= r) {return {tr[u].sf, tr[u].s, tr[u].f};}ll mid = (tr[u].l + tr[u].r) >> 1;ll ansSF = -inf, ansS = -inf, ansF = -inf, ss = -inf, ff = -inf;if (l <= mid) {auto tmp = querySF(u << 1, l, r);ansSF = max(ansSF, tmp.sf);ansS = max(ansS, tmp.s);ansF = max(ansF, tmp.f);ss = max(ss, tmp.s);}if (r > mid) {auto tmp = querySF(u << 1 | 1, l, r);ansSF = max(ansSF, tmp.sf);ansS = max(ansS, tmp.s);ansF = max(ansF, tmp.f);ff = max(ff, tmp.f);}ansSF = max(ansSF, ss + ff);return {ansSF, ansS, ansF};
}ll a[5][N];
ll pref[5][N];struct seg {ll l, r;ll k;
};seg segs[N];signed main() {ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);ll n, q;cin >> n >> q;bool checkflag = 0;for (ll i = 0; i < 3; ++i) {for (ll j = 1; j <= n; ++j) {cin >> a[i][j];if (a[i][j] > 0) checkflag = 1;pref[i][j] = pref[i][j - 1] + a[i][j];}}for (ll i = 1; i <= n; ++i) {s[i] = pref[0][i] - pref[1][i - 1];f[i] = pref[1][i] - pref[2][i - 1] + pref[2][n];}build(1, 1, n + 5);for (ll i = 0; i <= n; ++i) dp[i] = -inf; // init dpll ans = -inf;for (ll i = 1; i <= q; ++i) { // refresh dp by scin >> segs[i].l >> segs[i].r >> segs[i].k;ll l = segs[i].l, r = segs[i].r;ll k = segs[i].k;ans = max(ans, querySF(1, l, r).sf - k);ll tmp = querySF(1, l, r).s - k;dp[r] = max(tmp, dp[r]);}for (ll i = 0; i <= n; ++i) s[i] = dp[i];build(1, 1, n + 5);sort(segs + 1, segs + q + 1, [&](auto a, auto b) {return a.r < b.r;});for (ll i = 1; i <= q; ++i) { // refresh dp by dpll l = segs[i].l, r = segs[i].r;ll k = segs[i].k;ll tmp = querySF(1, (l - 1 == 0 ? l : l - 1), (r - 1 == 0 ? r : r - 1)).s - k;modify(1, r, r, tmp);ans = max(ans, querySF(1, (l - 1 == 0 ? l : l - 1), r).sf - k);}cout << ans << endl;return 0;
}
Codeforces Round #775 - F. Serious Business相关推荐
- C. Tyler and Strings(组合数学,树状数组维护前缀和)(Codeforces Round #775 (Div. 1, based on Moscow Open Olympiad i)
对我来说比较困难的一题了,尝试着自己写了一下,调不出来遂放弃. Codeforces Round #775 (Div. 1, based on Moscow Open Olympiad in Info ...
- Codeforces Round #775 (Div. 2, based on Moscow Open Olympiad in Informatics)简训
Codeforces Round #775 (Div. 2, based on Moscow Open Olympiad in Informatics)简训 导语 涉及的知识点 题目 A Game B ...
- Educational Codeforces Round 9 F. Magic Matrix 最小生成树
F. Magic Matrix 题目连接: http://www.codeforces.com/contest/632/problem/F Description You're given a mat ...
- Educational Codeforces Round 14 - F (codeforces 691F)
题目链接:http://codeforces.com/problemset/problem/691/F 题目大意:给定n个数,再给m个询问,每个询问给一个p,求n个数中有多少对数的乘积≥p 数据范围: ...
- Educational Codeforces Round 39 F Largest Beautiful Number
传送门 暴力DP dp[i][j][k] 从j 到 k 发f(x) 的大小, #include <bits/stdc++.h> using namespace std; typedef l ...
- 双联通分量求简单环(Educational Codeforces Round 42: F. Simple Cycles Edges)
题意: n个点m条边的无向图,问有哪些边在一个简单环上,按顺序输出这些边的编号 思路: 对于无向图求出每个双联通分量,对于每个双联通分量,如果点的个数==边的个数,那么这个双联通分量就是个简单环,输出 ...
- Educational Codeforces Round 51: F. The Shortest Statement(最短路+LCA)
F. The Shortest Statement 题意: n个点m条边(m≤n+20)的无向连通图,Q次询问,每次求出给定两点的最短路 思路: 将题意转换一下,给你一棵n个节点的树,并且这个树上还有 ...
- Educational Codeforces Round 50: F. Relatively Prime Powers(莫比乌斯函数)
F. Relatively Prime Powers 题意: 给你一个n,问满足在[2,n]范围内有多少个数是非次方数(也就是不是这样的) 思路: 答案就是 原理是利用容斥,注意n开i次根是向下取整( ...
- Codeforces Round 775(Div.2) Problem C Weird Sum(匿名函数的使用)
原题链接 C++ Lambda函数(匿名函数)的使用方法 首先了解一下 C++ 匿名函数的基本使用方法 基本语法 //[捕获列表](参数列表)->返回类型{函数体} auto f = []( ...
最新文章
- androidstudio判断手指滑动方向_方向盘的黑科技有多“黑”
- flask从服务器获取html页面,flask的ajax、获取服务器数据、放到前端页面、如果数据存在显示标签、如果不存在不显示标签...
- Smali文件添加try/catch语句,出现“invalid use of move-exception”异常
- 针对Chrome的css的hack写法
- IE6,IE7,FF等浏览器不兼容原因及解决办法(转)
- docker 容器基础技术
- 【C++深度剖析教程37】类模板的概念和意义
- 知道一点怎么设直线方程_直线初步
- 发送消息的时候,会指定用户,其实还可以定义媒介为脚本,让用户执行这个脚本...
- 全面综合的管理平台,让所有网络都有管理员
- for input string:是什么原因出现的_「汽车空调异味」周期性出现:原因是什么呢?...
- U盘量产U盘扩容和U盘芯片检测
- 26岁,2020 - 观《人生七年》
- 使用Cytoscape 的BinGO插件绘制GO通路关系图
- 用python做网站的步骤_Python建网站的步骤
- 285页解析百度、阿里、腾讯前端面试题,通关秘籍请收好!
- python_IED工具下载(pycharm)_windows版
- 调起APP功能的实现
- java实现excel打印_java实现 excel 打印 问题
- VS2017MFC发布打包