HDU 6161.Big binary tree 二叉树

Big binary tree

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 670    Accepted Submission(s): 235


Problem Description

You are given a complete binary tree with n nodes. The root node is numbered 1, and node x's father node is  x/2. At the beginning, node x has a value of exactly x. We define the value of a path as the sum of all nodes it passes(including two ends, or one if the path only has one node). Now there are two kinds of operations:
1.  change u x Set node u's value as x(1≤u≤n;1≤x≤10^10)
2.  query u Query the max value of all paths which passes node u.
 

 

Input
There are multiple cases.
For each case:
The first line contains two integers n,m(1≤n≤10^8,1≤m≤10^5), which represent the size of the tree and the number of operations, respectively.
Then m lines follows. Each line is an operation with syntax described above.
 

 

Output
For each query operation, output an integer in one line, indicating the max value of all paths which passes the specific node.
 

 

Sample Input
6 13
query 1
query 2
query 3
query 4
query 5
query 6
change 6 1
query 1
query 2
query 3
query 4
query 5
query 6
 

 

Sample Output
17
17
17
16
17
17
12
12
12
11
12
12
 

 

Source
 

 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   6216  6215  6214  6213  6212 
 
题意:题目是给一棵完全二叉树,从上到下从左到右给每个节点标号,每个点有权值,初始权值为其标号,然后有两种操作: 
1、把u点权值改为x 
2、查询所有经过u点的路径中,路径上的点权和最大。
思路:每次修改只会改变log(n)个节点,最多改变log(n)*m个节点,约为2.7*10^6个节点,但是n最大为10^8,所以只能用map存储。没有修改过的结点不需要存储,因为没有修改过的话一定是右儿子大,有以只需要往右走就能寻找到以当前点为根的最大路径点权和,但是如果左边的结点数比右边的多的话就需要往左了。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<bitset>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
#define bug(x) cout<<"bug"<<x<<endl;
#define PI acos(-1.0)
#define eps 1e-8
const int N=2e5+100,M=1e5+100;
const int inf=0x3f3f3f3f;
const ll INF=1e18+7,mod=1e9+7;
ll n;
char s[100];
map<ll,ll> vis,deep;
ll getnum(ll tmp)
{
    ll ans=0;
    while(tmp<=n)
    {
        if(deep.find(tmp)!=deep.end()) return ans+deep[tmp];
        if(vis.find(tmp)==vis.end()) ans+=tmp;
        else ans+=vis[tmp];
        ll tmp1=tmp<<1,tmp2=tmp<<1|1;
        int h1=0,h2=0;
        while(tmp1<=n) tmp1=tmp1<<1,h1++;
        while(tmp2<=n) tmp2=tmp2<<1,h2++;
        if(h1==h2) tmp=tmp<<1|1;
        else tmp=tmp<<1;
    }
    return ans;
}
void getchild(ll u,ll &ch1,ll &ch2)
{
    ch1=getnum(u<<1),ch2=getnum(u<<1|1);
}
int main()
{
    int m;
    while(scanf("%lld%d",&n,&m)!=EOF)
    {
        vis.clear(),deep.clear();
        for(int i=1; i<=m; i++)
        {
            ll u,x;
            scanf("%s %lld",s,&u);
            if(s[0]=='c')
            {
                scanf("%lld",&x);
                vis[u]=x;
                while(u>=1)
                {
                    ll ch1,ch2;
                    getchild(u,ch1,ch2);
                    if(vis.find(u)==vis.end()) deep[u]=max(ch1,ch2)+u;
                    else deep[u]=max(ch1,ch2)+vis[u];
                    u/=2;
                }
            }
            else
            {
                ll ch1,ch2;
                getchild(u,ch1,ch2);
                u=ch1>ch2?(u<<1):(u<<1|1);
                ll cou=max(ch1,ch2);
                ll ans=0;
                while(u>1)
                {
                    if(vis.find(u/2)==vis.end()) cou+=u/2;
                    else cou+=vis[u/2];
                    ans=max(ans,getnum(u^1)+cou);
                    u/=2;
                }
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/GeekZRF/p/7606236.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值