hdu 6161
来源:互联网 发布:windows 桌面版qq 编辑:程序博客网 时间:2024/05/18 00:46
题目链接:点击打开链接
题解思路:求通过此点求最大路径和无非两种:1.路径通过节点的两个儿子2.路径通过节点的一个儿子和自己父节点的另一个儿子,那么我们用dp[i]表示节点i通过他的一个儿子到叶子节点最大和,那么就可以递推更新答案了。
代码:
#include <queue>#include <algorithm>#include <cmath>#include <cstdio>#include <iostream>#include <cstring>#include <set>#include <map>using namespace std;typedef long long ll;const int mx = 1e5+10;int n,m;char str[20];map<int,ll>val,dp;ll cal(ll x){ if(x>n) return 0; if(dp.count(x)) return dp[x]; ll lson = 0,rson = 0,ts; ts = x; while((ts<<1)<=n){ ts <<= 1; lson++; } ts = x; while((ts<<1|1)<=n){ ts = (ts<<1|1); rson++; } if(rson!=lson) ts = n; ll ret = 0; while(ts>=x){ ret += (val.count(ts)?val[ts]:ts); ts >>= 1; } return ret;}void update(ll x,ll v){ val[x] = v; while(x){ dp[x] = max(cal(x<<1),cal(x<<1|1))+(val.count(x)?val[x]:x); x >>= 1; }}ll query(ll x){ ll ans = cal(x<<1)+cal(x<<1|1)+(val.count(x)?val[x]:x); ll ret = cal(x); while((x>>1)){ int flag = (x%2); x >>= 1; ret += (val.count(x)?val[x]:x); if(flag) ans = max(ans,ret + cal(x<<1)); else ans = max(ans,ret + cal(x<<1|1)); } return ans;}int main(){ while(~scanf("%d%d",&n,&m)){ ll x , y; val.clear(); dp.clear(); while(m--){ scanf("%s",str); if(str[0]=='q'){ scanf("%lld",&x); printf("%lld\n",query(x)); } else { scanf("%lld%lld",&x,&y); update(x,y); } } } return 0;}
阅读全文
0 0
- HDU 6161
- hdu 6161
- hdu 6161
- HDU 6161 乱搞+dp
- hdu
- hdu
- HDU
- hdu ()
- hdu
- hdu
- HDU
- HDU
- hdu
- hdu
- HDU
- Hdu
- hdu
- hdu-
- JavaSE 网络编程
- SpringMVC拦截器实现登录验证的例子
- 解决Ubuntu 切换root失败问题
- odl-boron-sr3之hello rpc
- 找到B字符串在A字符串中出现的所有位置的集合
- hdu 6161
- 自己搭建自动化巡检系统(一) 环境准备系统连接gns3
- numpy中函数nditer的作用
- caffe-windows添加自己的工程
- oracle子查询嵌套查询
- QT5布局管理——分割窗口QSplitter类
- 线段树题目整合
- 超实用的HTML 5接口全方位测试总结文
- 【51Nod1120】机器人走方格 V3