Codeforces 935E Fafa and Ancient Mathematics(表达式转树 + 树型DP)
题目链接 Codeforces Round #465 (Div. 2) Problem E
题意 给定一个表达式,然后用$P$个加号和$M$个减号填充所有的问号(保证问号个数等于$P + M$)
求可以形成的表达式的最大值。
先把表达式转成一棵树,然后在树上DP。
题目保证了$min(P, M) <= 100$, 为了提高效率,我们选择用少的运算符号作为DP的第二维。
对$P$和$M$的大小关系进行分类讨论。
当$P < M$时,
设$f[i][j]$表示$i$代表的子树里面填$j$个加号能得到的结果的最大值。
$c[i][j]$表示$i$代表的子树里面填$j$个减号能得到的结果的最小值。
那么转移就是
$f[x][i+j+1] = max(f[x][i+j+1], f[l][i] + l[r][j])$
$f[x][i+j] = max(f[x][i+j], f[l][i] - c[r][j])$
$c[x][i+j+1] = min(c[x][i+j+1], c[l][i] + c[r][j])$
$c[x][i+j] = min(c[x][i+j], c[l][i] - f[r][j])$
当$P > M$时,
设$f[i][j]$表示$i$代表的子树里面填$j$个加号能得到的结果的最大值。
$c[i][j]$表示$i$代表的子树里面填$j$个减号能得到的结果的最小值。
设个时候转移方程为
$f[x][i+j] = max(f[x][i+j], f[l][i] + l[r][j])$
$f[x][i+j+1] = max(f[x][i+j+1], f[l][i] - c[r][j])$
$c[x][i+j] = min(c[x][i+j], c[l][i] + c[r][j])$
$c[x][i+j+1] = min(c[x][i+j+1], c[l][i] - f[r][j])$
程序里把两种情况合起来写了,看起来更加简洁。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i)
#define dec(i, a, b) for (int i(a); i >= (b); --i)
#define MP make_pair
#define fi first
#define se second typedef long long LL; const int N = 1e4 + 10;
const int M = 105;
const int inf = 1e9; char st[N];
int val[N];
int p, m, n;
int f[N][M], c[N][M];
vector <int> v[N];
stack <int> stk; inline void upmax(int &a, int b){ a = max(a, b);}
inline void upmin(int &a, int b){ a = min(a, b);} void dfs(int x, int t){
rep(i, 0, M - 1) f[x][i] = -inf, c[x][i] = inf;
if (val[x]){
f[x][0] = c[x][0] = val[x];
return;
} int l = v[x][0], r = v[x][1];
dfs(l, t), dfs(r, t); rep(i, 0, M - 1) if (f[l][i] > -inf){
rep(j, 0, M - 1) if (f[r][j] > -inf){
upmax(f[x][i + j + t], f[l][i] + f[r][j]);
upmax(f[x][i + j + (t ^ 1)], f[l][i] - c[r][j]);
upmin(c[x][i + j + t], c[l][i] + c[r][j]);
upmin(c[x][i + j + (t ^ 1)], c[l][i] - f[r][j]);
}
}
} int main(){ scanf("%s%d%d", st, &p, &m); for (int i = 0; st[i]; ++i){
if (st[i] == '(') stk.push(++n);
else if (st[i] == ')'){
int t = stk.top();
stk.pop();
if (!stk.empty()) v[stk.top()].push_back(t);
} else if (st[i] >= '1' && st[i] <= '9'){
if (stk.empty()) return 0 * printf("%d\n", st[i] - '0');
v[stk.top()].push_back(++n);
val[n] = st[i] - '0';
}
} dfs(1, p < m);
printf("%d\n", f[1][min(p, m)]);
return 0;
}
Codeforces 935E Fafa and Ancient Mathematics(表达式转树 + 树型DP)的更多相关文章
- Codeforces 935E Fafa and Ancient Mathematics dp
Fafa and Ancient Mathematics 转换成树上问题dp一下. #include<bits/stdc++.h> #define LL long long #define ...
- CodeForces 935E Fafa and Ancient Mathematics (树形DP)
题意:给定一个表达式,然后让你添加 n 个加号,m 个减号,使得表达式的值最大. 析:首先先要建立一个表达式树,这个应该很好建立,就不说了,dp[u][i][0] 表示 u 这个部分表达式,添加 i ...
- 【学术篇】CF935E Fafa and Ancient Mathematics 树形dp
前言 这是一道cf的比赛题.. 比赛的时候C题因为自己加了一个很显然不对的特判WA了7次但找不出原因就弃疗了... 然后就想划水, 但是只做了AB又不太好... 估计rating会掉惨 (然而事实证明 ...
- 2018.12.12 codeforces 935D. Fafa and Ancient Alphabet(概率dp)
传送门 概率dp水题. 题意简述:给你数字表的大小和两个数列,数列中为0的数表示不确定,不为0的表示确定的,求第一个数列字典序比第二个数列大的概率. fif_ifi表示第i ni~ ni n位第一个 ...
- Codeforces 935D Fafa and Ancient Alphabet
题目链接 题意 给定两个\(n\)位的\(m\)进制数\(s1,s2\),所有出现的\(0\)均可等概率地被其他数字替换,求\(s1\gt s2\)的概率. 思路 从高位到低位,根据每一位上相应的\( ...
- [Codeforces 464E] The Classic Problem(可持久化线段树)
[Codeforces 464E] The Classic Problem(可持久化线段树) 题面 给出一个带权无向图,每条边的边权是\(2^{x_i}(x_i<10^5)\),求s到t的最短路 ...
- Codeforces Good Bye 2015 D. New Year and Ancient Prophecy 后缀数组 树状数组 dp
D. New Year and Ancient Prophecy 题目连接: http://www.codeforces.com/contest/611/problem/C Description L ...
- Codeforces 552E - Vanya and Brackets【表达式求值】
给一个只有加号和乘号的表达式,要求添加一对括号使得最后结果最大.表达式长度5000,乘号最多12个,表达式中数字只有1位. 左括号一定在乘号右边,右括号一定在乘号左边,因为如果不是这样的话,一定可以调 ...
- codeforces 552 E. Vanya and Brackets 表达式求值
题目链接 讲道理距离上一次写这种求值的题已经不知道多久了. 括号肯定是左括号在乘号的右边, 右括号在左边. 否则没有意义. 题目说乘号只有15个, 所以我们枚举就好了. #include <io ...
随机推荐
- 关于p标签的嵌套问题
今天群里问了一个p的问题,初看我觉得恩这么简单我应该知道. 他代码如下: <!DOCTYPE HTML> <html> <head> <meta charse ...
- 设计模式之第22章-组合模式(Java实现)
设计模式之第22章-组合模式(Java实现) “鱼哥,有没有什么模式是用来处理树形的“部分与整体”的层次结构的啊.”“当然”“没有?”“有啊.别急,一会人就到了.” 组合模式之自我介绍 “请问你是?怎 ...
- Percona-Tookit工具包之pt-summary
Preface As a dba,We are obliged to master several basic tools(such as vmstat,top,netstat,ios ...
- python中subprocess.Popen执行命令并持续获取返回值
先举一个Android查询连接设备的命令来看看Python中subprocess.Popen怎么样的写法.用到的命令为 adb devices. import subprocess order='ad ...
- day06_02 元组
1.0 元组 元组被称为只读列表,即数据可以被查询,但不能被修改,所以,列表的切片操作同样适用于元组.元素卸载小括号(())里,元素之间用逗号隔开. tup1 = () #空元组 tup2 = (20 ...
- python学习总结----时间模块 and 虚拟环境(了解)
time - sleep:休眠指定的秒数(可以是小数) - time:获取时间戳 # 获取时间戳(从1970-01-01 00:00:00到此刻的秒数) t = time.time() print(t ...
- centos7安装Logwatch配合msmtp邮件客户端发送服务器监控分析日志
########################### #DATE 2016-07-29 # #Authur by Denilas Yeung ...
- 【转】TCP通信的三次握手和四次撒手的详细流程(顿悟)
TCP(Transmission Control Protocol) 传输控制协议 三次握手 TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接: 位码即tcp标志位 ...
- hdu 2821 Pusher (dfs)
Pusher Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/65536 K (Java/Others)Total Subm ...
- 【距离GDOI:131天】 后缀数组完毕
用了近两周的时间,终于把罗神那篇后缀数组应用看完了,题目也写了一遍,T了无数次...详见前几篇博文... 后缀数组很重要的是那个height数组,可以用来做各种奇奇怪怪的东西...常用方法去是去二分, ...