hdu 6161 Big binary tree(脑洞)

题目链接:hdu 6161 Big binary tree

题意:

给你n个点,和m条操作,一开始n个点构成一个完全二叉树,每个点的权值为该点编号。

每个操作可能为

1.询问经过x点的最大路径(该路径上的点权之和最大)。

2.修改x点的权值。

题解:

下面是官方题解

考虑dp,f(x)表示从点x开始向下走得到的最大的点权和,查询直接从x开始向上走更新答案即可。
考虑快速算 f(x) 对于子树内没有被修改过的点的 f(x) 可以快速分类讨论算出,而不满足本条件的点只有 O(mlogm) 个,在hash上dp即可。

我的做法类似,然后多开了个g(x)表示x点的值,每次计算的时候是递归计算的,没有dp。我算f(x)的时候是一直往右儿子走,但是由于这是一棵完全二叉树,不一定会满,所以有一个节点的f(x)会错,那个is(x)就是记录的那条错误的链上的点的信息。

 1 #include<bits/stdc++.h>
 2 #define mst(a,b) memset(a,b,sizeof(a))
 3 #define F(i,a,b) for(int i=(a);i<=(b);++i)
 4 using namespace std;
 5 typedef long long ll;
 6 
 7 map<int,ll>mp,mmp,is;
 8 int n,m;
 9 
10 ll f(int x)
11 {
12     if(x>n)return 0;
13     if(mp.find(x)!=mp.end())return mp[x];
14     if(is.find(x)!=is.end())return is[x];
15     ll ans=0;
16     while(x<=n)ans+=x,x=x*2+1;
17     return ans;
18 }
19 
20 ll g(int x)
21 {
22     if(x>n)return 0;
23     if(mmp.find(x)!=mmp.end())return mmp[x];
24     return x;
25 }
26 
27 void chang(int a,ll b)
28 {
29     mp[a]=b+max(f(a*2),f(a*2+1));
30     mmp[a]=b;
31     for(a/=2;a>=1;a/=2)
32     {
33         mp[a]=g(a)+max(f(a*2),f(a*2+1));
34     }
35 }
36 
37 void dfs(int x,ll sum,ll &ans)
38 {
39     if(x==1)return;
40     int fx=x/2;
41     ans=max(ans,sum+g(fx)+f(x^1));
42     dfs(fx,sum+g(fx),ans);
43 }
44 
45 ll query(int x)
46 {
47     ll ans=f(x*2)+f(x*2+1)+g(x);
48     dfs(x,f(x),ans);
49     return ans;
50 }
51 
52 int main(){
53     while(~scanf("%d%d",&n,&m))
54     {
55         mp.clear(),mmp.clear(),is.clear();
56         ll now=0;int x=n;
57         while(x>=1)now+=x,is[x]=now,x/=2;
58         F(i,1,m)
59         {
60             char op[10];int a;ll b;
61             scanf("%s",op);
62             if(*op=='q')
63             {
64                 scanf("%d",&a);
65                 printf("%lld\n",query(a));
66             }else scanf("%d%lld",&a,&b),chang(a,b);
67         }
68     }
69     return 0;
70 }
View Code

 

posted @ 2017-08-23 14:50  bin_gege  阅读(249)  评论(0编辑  收藏  举报